package com.css.influence.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.attachment.entity.AttachmentInfoEntity;
import com.css.attachment.entity.ParsingResult;
import com.css.attachment.service.impl.AttachmentServiceImpl;
import com.css.casualties.mapper.pop.service.PopService;
import com.css.config.QueueConfig;
import com.css.config.ThreadPoolConfig;
import com.css.entity.*;
import com.css.fault.entity.ActiveFault;
import com.css.fault.service.ActiveFaultService;
import com.css.influence.entity.*;
import com.css.influence.entity.MessageLog.service.MessageLogService;
import com.css.influence.mapper.*;
import com.css.influence.util.EnvelopeFactory;
import com.css.influence.vo.EarthquakeModel;
import com.css.influence.vo.InfluenceTitleVO;
import com.css.influence.vo.InfluenceVO;
import com.css.influence.vo.ToEvaluateVO;
import com.css.mapper.*;
import com.css.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jcraft.jsch.*;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.geotools.data.FeatureWriter;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.util.GeometricShapeFactory;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.postgis.Geometry;
import org.postgis.PGgeometry;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Dbj
 * @date 2024年09月04日  10:46
 * 影响场service
 */
@Component
@Slf4j
public class InfluenceService extends ServiceImpl<InfluenceMapper, SettingSeismicInfluenceflied> {

    @Resource
    AttachmentServiceImpl attachmentService;

    @Resource
    RabbitTemplate rabbitTemplate;

    /**
     * 定义地球半径（米）
     */
    private final double R_EARTH = 6371000;

    @Value("${image.localDir}")
    private String localDir;
    @Value("${file.path}")
    private String filePath;

    //失败重试次数
    @Value("${spring.rabbitmq.failedRetry}")
    private Integer failedRetry;

    @Resource
    FileMapper fileMapper;

    @Resource
    MessageLogService messageLogService ;

    @Resource
    ActiveFaultService activeFaultService;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    EarthQuakeInfluenceService earthQuakeInfluenceService;
    @Resource
    PopService popService;
    @Resource
    InfluenceAreaPersionService influenceAreaPersionService;
    @Resource
    InfluencehospitalSchoolReservoirService influencehospitalSchoolReservoirService;
    @Resource
    ReserviorMapper reserviorMapper;
    @Resource
    ReDataSynthesizeMapper reDataSynthesizeMapper;
    @Resource
    ReDataJuniorcollegeMapper reDataJuniorcollegeMapper;
    @Resource
    ReDataKindergartenMapper reDataKindergartenMapper;
    @Resource
    ReDataPrimaryschoolMapper reDataPrimaryschoolMapper;
    @Resource
    ReDataMiddleschoolMapper reDataMiddleschoolMapper;
    @Resource
    ReDataHighacademyMapper reDataHighacademyMapper;
    @Resource
    SettingInfluenceMapper settingInfluenceMapper;
    @Resource
    DivisionManagerMapper divisionManagerMapper;
    @Resource
    DataAirPortMapper dataAirPortMapper;
    @Resource
    DataAirPortNumMapper dataAirPortNumMapper;
    @Resource
    ModelMapper modelMapper;
    private static final Map<String, Integer> retryMap = new ConcurrentHashMap<>();
    @Resource
    InfluenceAirPortMapper influenceAirPortMapper;
    @Resource
    DataHouseBrickworkMapper dataHouseBrickworkMapper;
    @Resource
    DataHouseBarMapper dataHouseBarMapper;
    @Resource
    DataHouseDancengMapper dataHouseDancengMapper;
    @Resource
    DataHouseQitaMapper dataHouseQitaMapper;
    @Resource
    DataHouseRebarMapper dataHouseRebarMapper;
    @Resource
    InfluenceHouseMapper influenceHouseMapper;
    @Resource
    InfluenceGdpMapper influenceGdpMapper;
    ThreadPoolExecutor executor = ThreadPoolConfig.exeBizThreadPoolExecutor;
    @Resource
    LineInfluenceMapper lineInfluenceMapper;

    @Resource
    DataGdpMapper dataGdpMapper;

    @Resource
    UsesetConfigMapper usesetConfigMapper;

    /**
     * 定义地球赤道周长（米）
     */
    private final double P_EARTH = 2 * Math.PI * R_EARTH;
//    /**
//     * 修正
//     */
//    @RabbitListener(queues = QUEUE_CREATE_INFLUENCE_REQ)
//    public void createSettingInfluence(Map<String,Object> paramMap,Channel channel,Message message) throws IOException {
//        log.info("收到消息了，开始生成影响场");
//        EarthquakeModel earthquakeModel = (EarthquakeModel) paramMap.get("earthquakeModel");
//        //2 重新生成  3、修正
//        Integer type = Integer.parseInt((String) paramMap.get("type"));
//        //保存
//        try{
//            Map<String, Object> map = createInfluence(earthquakeModel,type);
//            List<SettingSeismicInfluenceflied> influenceData = (List<SettingSeismicInfluenceflied>) map.get("influenceData");
//            if(ObjectUtils.isNotEmpty(influenceData) && influenceData.size()>0){
//                 saveBatch(influenceData);
//                 rabbitTemplate.convertAndSend(EXCHANGE_INFLUENCE,KEY_CREATE_INFLUENCE_ACK,"影响场创建成功");
//            }
//        }catch (Exception e){
//            rabbitTemplate.convertAndSend(EXCHANGE_INFLUENCE,KEY_CREATE_INFLUENCE_ACK,"影响场创建失败");
//        }finally {
//            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
//        }
//    }

    public static void main(String[] args) throws Exception {
        //uploadFile("D:\\data\\file\\upload\\files\\2025\\03\\11\\10-55-02【测试】D湖北省潜江市潜江市6.5级地震\\【测试】D湖北省潜江市潜江市6.5级地震6度及以上影响场.zip","/data/file/upload/files/2025/03/11/10-55-02【测试】D湖北省潜江市潜江市6.5级地震/【测试】D湖北省潜江市潜江市6.5级地震6度及以上影响场.zip");
        StringBuilder temp =new StringBuilder();
        createDateMkdir(temp);
        System.out.println(temp.toString());
    }
    public static void uploadFile( String localFilePath, String remoteFilePath) throws JSchException, IOException {
        String host = "10.5.92.112";
        String user = "yingji";
        String password = "CENC@dzj_88015563";
        int port = 22;
        JSch jsch = new JSch();
        Session session = jsch.getSession(user, host, port);
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();

        //修改目标目录的权限
        int i = remoteFilePath.lastIndexOf("/");
        String remoteDirectory = remoteFilePath.substring(0,i+1);
        com.jcraft.jsch.Channel  channel = session.openChannel("exec");
        ((ChannelExec) channel).setCommand("chmod 775 " + remoteDirectory);
        channel.setInputStream(null);
        ((ChannelExec) channel).setErrStream(System.err);
        channel.connect();

        InputStream in = channel.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        int exitStatus = channel.getExitStatus();
        if (exitStatus == 0) {
            System.out.println("目录权限更改成功");
        } else {
            System.out.println("目录权限更改失败，退出状态码: " + exitStatus);
        }

        channel.disconnect();

        channel = session.openChannel("sftp");
        channel.connect();
        ChannelSftp sftpChannel = (ChannelSftp) channel;

        FileInputStream fis = null;
        try {
            File file = new File(localFilePath);
            fis = new FileInputStream(file);
            sftpChannel.put(fis, remoteFilePath);
        } catch (Exception e){
            e.printStackTrace();
        }finally {
            if (fis != null) {
                fis.close();
            }
            sftpChannel.disconnect();
            channel.disconnect();
            session.disconnect();
            System.out.println("-------影响场文件同步112服务器成功");
        }
    }

    public void createInfluence(EarthquakeModel earthquakeModel ,String angle,Map<String,Object> resultMap) throws Exception {
        EarthQuake earthQuake = earthquakeModel.getEarthQuake();
        log.error("地震id"+earthQuake.getId()+"-- 创建影响场"+"|| 开始。>> 参数:"+JSON.toJSONString(earthquakeModel));
        try{
            //获取模型是圆形还是椭圆形
            Double latitude = earthQuake.getLatitude();
            Double longitude = earthQuake.getLongitude();
            Model model = earthquakeModel.getModel();
            //时间作为影响场版本（客户要求）
            Date version = DateUtil.date();
            //影响场发送给评估计算的消息实体
            ToEvaluateVO vo = null;
            //影响场模型没匹配到则不需要执行影响场的生成逻辑
            int val = 12;
            int max = val;
            //影响场数据集合
            List<SettingSeismicInfluenceflied> resultList = new ArrayList<>();
            List<LineSettingSeismicInfluenceflied> lineResultList = new ArrayList<>();
            //发送给钉钉微信ftp等消息服务的数据集合
            List<SettingSeismicInfluenceflied> intensityList = new ArrayList<>();
            if (model!=null) {
                String category = model.getCategory();
                //编码 4326 还是4490
                Integer code = model.getCode();
                if(ObjectUtils.isEmpty(code)){
                    code = 4490;
                }
                //1、圆模型  2、椭圆模型  3、线源模型
                //椭圆影响场最小烈度是从6度开始  圆是从4度开始   最大烈度都是12度
                //int val = getInitVal(category);
                //地震烈度衰减关系模型
                BigDecimal longRatio1 = model.getLongRatio1();
                BigDecimal longRatio2 = model.getLongRatio2();
                BigDecimal longRatio3 = model.getLongRatio3();
                BigDecimal longRatio4 = model.getLongRatio4();
                String longSymbol = model.getLongSymbol();
                BigDecimal shortRatio1 = model.getShortRatio1();
                BigDecimal shortRatio2 = model.getShortRatio2();
                BigDecimal shortRatio3 = model.getShortRatio3();
                BigDecimal shortRatio4 = model.getShortRatio4();
                String shortSymbol = model.getShortSymbol();
                BigDecimal longX = BigDecimal.ZERO;
                BigDecimal shortY = BigDecimal.ZERO;
                boolean isNa = true;
                List<ToEvaluateVO.Influence> influenceList = new ArrayList<>();
                double innerArea = 0.0;
                for(;val>=5;val--){
//                if (val == 12) {
//                    isNa = true;
//                }
                    SettingSeismicInfluenceflied intensity = new SettingSeismicInfluenceflied();
                    SettingSeismicInfluenceflied influenceflied = new SettingSeismicInfluenceflied();
                    //震级
                    BigDecimal earthquakeMagnitude = BigDecimal.valueOf(earthQuake.getEarthquakeMagnitude());
                    influenceflied.setEarthquakeLevel(earthquakeMagnitude);
                    //地震影响场烈度
                    influenceflied.setDzIntensity(String.valueOf(val));
                    influenceflied.setIntensityShow(intensityMap().get(String.valueOf(val)));
                    influenceflied.setIntensityChinaShow(IntensityUtil.getUpperNum(String.valueOf(val)));
                    //长轴：Ia=4.9024+1.3485M-3.9738Lg(Ra+13)
                    //Ia为长轴烈度 M为震级，Ra为烈度为I时长半轴的长度
                    //根据公式计算得到Ra，如果值为负数，则舍掉，为正的则留下
                    //烈度为Ia时长半轴的长度
                    BigDecimal ra = BigDecimal.ZERO;
                    double a = (longRatio1.add(longRatio2.multiply(earthquakeMagnitude)).subtract(BigDecimal.valueOf(val)))
                            .divide(longRatio3, 8, RoundingMode.UP).doubleValue();
                    if ("ln".equals(longSymbol)) {
                        ra = BigDecimal.valueOf(Math.pow(Math.E, a)).subtract(longRatio4);
                    } else if ("lg".equals(longSymbol)) {
                        ra = BigDecimal.valueOf(Math.pow(10, a)).subtract(longRatio4);
                    }
                    Map<String,Object> map = new HashMap<>();
                    //生成椭圆影响场
                    if("2".equals(category)){
                        // 短轴：Ib=4.3517+ 1.2192M-3.7429Lg(Rb+6)
                        //式中，Ib分别为短轴烈度，M为震级，Rb分别为烈度为I时短半轴的长度
                        //根据公式计算得到Rb，如果值为负数，则舍掉，为正的则留下
                        //烈度为Ib时短半轴的长度
                        BigDecimal rb = BigDecimal.ZERO;
                        double b = (shortRatio1.add(shortRatio2.multiply(earthquakeMagnitude)).subtract(BigDecimal.valueOf(val))).divide(shortRatio3, 8, RoundingMode.UP).doubleValue();
                        if ("lg".equals(shortSymbol)) {
                            rb = BigDecimal.valueOf(Math.pow(10, b)).subtract(shortRatio4);
                        } else if ("ln".equals(shortSymbol)) {
                            rb = BigDecimal.valueOf(Math.pow(Math.E, b)).subtract(shortRatio4);
                        }
                        if (ra.compareTo(BigDecimal.ZERO) < 0) {
                            max--;
                            //Ra为负数
                            continue;
                        }
                        if (rb.compareTo(BigDecimal.ZERO) < 0) {
                            max--;
                            //Rb为负数
                            continue;
                        }
//                    //长轴长度
                        ra = ra.multiply(BigDecimal.valueOf(2)).setScale(1, RoundingMode.HALF_UP);
//                    //短轴长度
                        rb = rb.multiply(BigDecimal.valueOf(2)).setScale(1, RoundingMode.HALF_UP);
                        influenceflied.setLongX(ra);
                        influenceflied.setShortY(rb);
                        influenceflied.setCategory("2");
                        if (!isNa) {
                            //环
                            map = createInfluenceEllipse(longitude,
                                    latitude,  influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    angle, longX.toString(), shortY.toString());
                        } else {
                            //生成椭圆影响场
                            map = createInfluenceEllipse(longitude,
                                    latitude, influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    angle, null, null);
                        }
                        influenceflied.setRuptureScale(BigDecimal.ZERO);
                    }else if("1".equals(category)){
                        //对于圆来说长短轴一样
                        //长轴长度
                        if (ra.compareTo(BigDecimal.ZERO) < 0) {
                            //Ra为负数
                            max--;
                            continue;
                        }
                        //长轴长度
                        ra = ra.multiply(BigDecimal.valueOf(2)).setScale(1, RoundingMode.HALF_UP);
//                    ra = ra.multiply(BigDecimal.valueOf(2)).setScale(1, RoundingMode.HALF_UP);
                        influenceflied.setLongX(ra);
                        influenceflied.setShortY(ra);
                        influenceflied.setCategory("1");
                        if (!isNa) {
                            //环
                            map = createInfluenceCircle(longitude,
                                    latitude,  influenceflied.getLongX().doubleValue(), longX.doubleValue());
                        } else {
                            //生成圆影响场
                            map = createInfluenceCircle(longitude,
                                    latitude, influenceflied.getLongX().doubleValue(), null);
                        }
                        influenceflied.setRuptureScale(BigDecimal.ZERO);
                    }else if("3".equals(category)){
                        //线源模型
                        //破裂尺度计算公式
                        //线源模型破裂尺度参数
                        BigDecimal ruptureScale1 = model.getRuptureScale1();
                        BigDecimal ruptureScale2 = model.getRuptureScale2();
                        BigDecimal subtract = earthquakeMagnitude.subtract(ruptureScale1);
                        BigDecimal ruptureScale = subtract.divide(ruptureScale2, 8, RoundingMode.UP);
                        BigDecimal L = BigDecimal.valueOf(Math.pow(10, ruptureScale.doubleValue()));
                        // 短轴：Ib=4.3517+ 1.2192M-3.7429Lg(Rb+6)
                        //式中，Ib分别为短轴烈度，M为震级，Rb分别为烈度为I时短半轴的长度
                        //根据公式计算得到Rb，如果值为负数，则舍掉，为正的则留下
                        //烈度为Ib时短半轴的长度
                        BigDecimal rb = BigDecimal.ZERO;
                        double b = (shortRatio1.add(shortRatio2.multiply(earthquakeMagnitude)).subtract(BigDecimal.valueOf(val))).divide(shortRatio3, 8, RoundingMode.UP).doubleValue();
                        if ("lg".equals(shortSymbol)) {
                            rb = BigDecimal.valueOf(Math.pow(10, b)).subtract(shortRatio4);
                        } else if ("ln".equals(shortSymbol)) {
                            rb = BigDecimal.valueOf(Math.pow(Math.E, b)).subtract(shortRatio4);
                        }
                        if (ra.compareTo(BigDecimal.ZERO) < 0) {
                            //Ra为负数
                            max--;
                            continue;
                        }
                        if (rb.compareTo(BigDecimal.ZERO) < 0) {
                            //Rb为负数
                            max--;
                            continue;
                        }
//                    //长轴长度
                        ra = ra.multiply(BigDecimal.valueOf(2)).setScale(1, RoundingMode.HALF_UP);
//                    //短轴长度
                        rb = rb.multiply(BigDecimal.valueOf(2)).setScale(1, RoundingMode.HALF_UP);
                        influenceflied.setLongX(ra);
                        influenceflied.setShortY(rb);
                        influenceflied.setCategory("3");
                        //生成线源影响场
                        if (!isNa) {
                            //环
                            map = createEnvelopeEllipse(longitude,
                                    latitude, influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    angle, longX.toString(), shortY.toString(),L.doubleValue());
                        }else{
                            map = createEnvelopeEllipse(longitude,
                                    latitude, influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    angle, null, null,L.doubleValue());
                        }
                        influenceflied.setRuptureScale(L);
                    }
                    double finalArea = 0.0;
                    if("1".equals(category) || "2".equals(category)){
                        Double area = (Double) map.get("area");
                        finalArea = area - innerArea;
                        innerArea = area;
                    }else if("3".equals(category)){
                        finalArea = (Double) map.get("area");
                    }
                    String influenceEllipse = (String) map.get("result");
                    String geom = this.baseMapper.selectGeomText(influenceEllipse);;
                    influenceflied.setUuid(UUID.randomUUID().toString().replace("-",""));
                    influenceflied.setEarthQuakeId(earthQuake.getId()+"");
                    isNa = false;
                    longX = influenceflied.getLongX();
                    shortY = influenceflied.getShortY();
                    PGgeometry pGgeometry = new PGgeometry(influenceEllipse);
                    Geometry geometry = pGgeometry.getGeometry();
                    //geometry.setSrid(model.getCode());
                    geometry.setSrid(4490);
                    influenceflied.setGeom(influenceEllipse);
                    // influenceflied.setGeom(influenceEllipse);
                    influenceflied.setOperateUserId("");
                    influenceflied.setOperateDeptId("");
                    influenceflied.setOperateTime(new Date());
                    influenceflied.setTriggerType(earthQuake.getEarthquakeType());
                    influenceflied.setModelId(model.getId());
                    influenceflied.setDataSource(earthQuake.getEarthquakeType()+"");
                    influenceflied.setVersion(version+"");
                    influenceflied.setType(earthquakeModel.getType());
                    influenceflied.setCode(4490+"");
                    influenceflied.setArea(finalArea);
                    influenceflied.setAngle(new BigDecimal(angle));
                    influenceflied.setRemark(earthQuake.getEarthquakeType()+"");
                    influenceflied.setGeomText(geom);
                    //影响场数据集合
                    resultList.add(influenceflied);
                    String lineGeom = influenceEllipse;
                    // 查询外壳与资源关联数量
                    String sql = "SELECT ST_ExteriorRing('"+lineGeom+"')";
                    lineGeom = jdbcTemplate.queryForObject(sql, String.class);
                    LineSettingSeismicInfluenceflied lineSettingSeismicInfluenceflied = new LineSettingSeismicInfluenceflied();
                    BeanUtils.copyProperties(influenceflied,lineSettingSeismicInfluenceflied);
                    lineSettingSeismicInfluenceflied.setGeom(lineGeom);
                    lineResultList.add(lineSettingSeismicInfluenceflied);
                    intensity.setDzIntensity(String.valueOf(val));
                    intensity.setGeom(influenceEllipse);
                    ToEvaluateVO.Influence influence = new ToEvaluateVO.Influence();
                    influence.setIntensity(val);
                    influence.setGeom(influenceEllipse);
                    influence.setCode(code+"");
                    influence.setArea(finalArea);
                    influenceList.add(influence);
                    if (val>=6) {
                        intensityList.add(intensity);
                    }
                }
                if(influenceList.size()>0){
                    vo = new ToEvaluateVO();
                    vo.setInfluenceList(influenceList);
                    vo.setEarthQuakeId(earthQuake.getId()+"");
                    vo.setInfluenceVersion(version);
                }else{
                    max = 3;
                }
                if(max==4){
                    //如果max=4表示沒有影响场生成，但是响应规则那是大于等于4的，所以不能发4。
                    max--;
                }
            }else{
                //3无实际意义就是与响应级别的设置约定
                max = 3;
            }
            //影响场信息
            resultMap.put("influenceData",resultList);
            //发送给钉钉微信ftp等消息服务的数据
            resultMap.put("intensityData",intensityList);
            //发送给响应级别的数据
            resultMap.put("maxIntensity",max);
            //发送给评估计算的数据
            resultMap.put("toEvaluateData",vo);
            //线影响场用于出图用
            resultMap.put("lineFluenceData",lineResultList);
        }catch (Exception e){
            e.printStackTrace();
            log.error("地震id"+earthQuake.getId()+"-- 创建影响场"+"|| 失败。>> 参数:"+JSON.toJSONString(earthquakeModel));
        }

//        return resultMap;
    }

    /**
     * 发送消息去响应级别
     */
    private void sendMsgToResponseLevel(EarthQuake earthQuake,String modelId,Integer max){
        Map<String,Object> responseLevelMap = new HashMap<>();
        responseLevelMap.put("earthQuakeLevel",earthQuake.getEarthquakeMagnitude());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String earthquakeTime = simpleDateFormat.format(earthQuake.getEarthquakeTime());
        responseLevelMap.put("earthquakeTime",earthquakeTime);
        responseLevelMap.put("earthquakeType",earthQuake.getEarthquakeType());
        responseLevelMap.put("bida",earthQuake.getBida());
        responseLevelMap.put("publish",earthQuake.getIsPublish());
        responseLevelMap.put("phoneConference",earthQuake.getPhoneConference());
        responseLevelMap.put("lon",earthQuake.getLongitude());
        responseLevelMap.put("lat",earthQuake.getLatitude());
        responseLevelMap.put("dept",earthQuake.getDepth());
        responseLevelMap.put("earthQuakeId",earthQuake.getId());
        responseLevelMap.put("modelId",modelId);
        responseLevelMap.put("referenceLocation",earthQuake.getReferenceLocation());
        responseLevelMap.put("earthQuakeTitle",earthQuake.getTitle());
        responseLevelMap.put("dataSourceKey","province_"+(earthQuake.getProvinceId()==null?12:earthQuake.getProvinceId()));
        responseLevelMap.put("province",StringUtils.isNotBlank(earthQuake.getBelongToProvince())?earthQuake.getBelongToProvince():"四川省");
        //获取最大烈度
        responseLevelMap.put("maxIntensity",max);
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_RESPONSELEVEL,responseLevelMap);
            log.error("地震id"+earthQuake.getId()+"-- 影响场给响应级别发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(responseLevelMap));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_RESPONSELEVEL,responseLevelMap);
                    flag = true;
                    log.error("地震id"+earthQuake.getId()+"-- 影响场给响应级别发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(responseLevelMap));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+earthQuake.getId()+"-- 影响场给响应级别发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(responseLevelMap));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(responseLevelMap), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_RESPONSELEVEL,status, content,"影响场发送消息给响应级别","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    //转换时间输出的方法
    public String getEarthquakeTimeStr(Date earthquakeTime){
        if (earthquakeTime != null){
            return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, earthquakeTime);
        }
        return "";
    }
    private void createAndSendZipToMessageService(List<SettingSeismicInfluenceflied> intensityList,EarthquakeModel  earthquakeModel) throws Exception {
        //文件命名:【测试】{地震名称}6 度及以上影响场(正式报、自动报不加【】)
        Map<String,Object> msgMap = null;
        EarthQuake earthQuake = earthquakeModel.getEarthQuake();
        String status = "成功";
        try{
            String name = earthQuake.getTitle()+"6度及以上影响场";
            String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
            String filePathDetail = DateUtils.parseDateToStr(DateUtils.RES_HH_MM_SS, earthQuake.getEarthquakeTime()) + earthQuake.getTitle();
            String path = filePath +dateDir + File.separator + filePathDetail  + File.separator;
            if (!new File(path).exists()) {
                FileUtil.mkdir(path);
            }
            //表示存在烈度>=6度的，则需要生成shp文件推送给消息发送服务
            String zipPath = path +"/"+ name + ".zip";
            if(ObjectUtils.isNotEmpty(intensityList) || intensityList.size()>0){
                double size = createShpDataFile(intensityList,name,zipPath);
                //发送消息
                msgMap = new HashMap<>();
                msgMap.put("type","结果数据");
                msgMap.put("property","快速评估影响场数据");
                msgMap.put("fileName",name + ".zip");
                msgMap.put("url",zipPath);
                msgMap.put("publish",earthquakeModel.getEarthQuake().getIsPublish());
                msgMap.put("earthQuakeId",earthQuake.getId()+"");
                msgMap.put("earthQuakeTitle",earthQuake.getTitle());
                msgMap.put("earthQuakeLevel",earthQuake.getEarthquakeMagnitude()+"");
                msgMap.put("earthQuakeTime",earthQuake.getEarthquakeTime());
                msgMap.put("earthquakeType",earthQuake.getEarthquakeType());
                msgMap.put("dataSourceKey",earthquakeModel.getDataSource());
                msgMap.put("province",earthQuake.getBelongToProvince());
                //保存文件信息
                //保存文件信息
                FileEntity fileDo = new FileEntity();
                //表示存在烈度>=6度的，则需要生成shp文件推送给消息发送服务
                //file.setConfigId(client.getId());
                fileDo.setName(name);
                fileDo.setFile(name + ".zip");
                fileDo.setMimeType("zip");
                fileDo.setEarthquakeId(earthquakeModel.getEarthQuake().getId());
                fileDo.setFileTypeId(3);
                fileDo.setConvertStatus(0);
                fileDo.setVersion(intensityList.get(0).getVersion());
                fileDo.setEarthquakeType(earthQuake.getEarthquakeType());
                String divisionCode = earthQuake.getDivisionCode();
                LambdaQueryWrapper<DivisionManagerDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                lambdaQueryWrapper.eq(DivisionManagerDO::getDivisionCode,divisionCode);
                String divisionName = divisionManagerMapper.selectOne(lambdaQueryWrapper).getDivisionName();
                fileDo.setCreatedUser(divisionName);
                fileDo.setFilePath(dateDir + File.separator +filePathDetail  +File.separator+name + ".zip");
                fileDo.setSource(3);
                fileDo.setFileSize(size+"kb");
                fileDo.setProvince(earthquakeModel.getEarthQuake().getBelongToProvince());
                fileDo.setEarthQuakeName(earthquakeModel.getEarthQuake().getTitle());
                fileMapper.insert(fileDo);
            }
            if(msgMap!=null){
                //发送消息给消息服务
                rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE_TO_CUSTOM,"",msgMap);
                log.error("地震id{}--影响场给钉钉微信ftp网盘邮箱发送消息 || 成功,>>参数:{}",earthquakeModel.getEarthQuake().getId(),JSON.toJSONString(msgMap));
            }
        }catch (Exception e){
            e.printStackTrace();
            if(msgMap!=null){
                boolean flag = false;
                for (int i=0;i<failedRetry;i++) {
                    try{
                        Thread.sleep(500);
                        //发送消息给消息服务
                        rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE_TO_CUSTOM,"",msgMap);
                        flag = true;
                        log.error("地震id{}--影响场给钉钉微信ftp网盘邮箱发送消息 || 成功,>>参数:{}",earthquakeModel.getEarthQuake().getId(),JSON.toJSONString(msgMap));
                        break;
                    }catch (Exception ignored){
                    }
                }
                if(!flag){
                    status = "失败";
                    log.error("地震id{}--影响场给钉钉微信ftp网盘邮箱发送消息 || 失败,>>参数:{}",earthquakeModel.getEarthQuake().getId(),JSON.toJSONString(msgMap));
                }
            }
        }finally {
            try{
                if(msgMap!=null){
                    LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(msgMap), new TypeReference<LinkedHashMap<String, Object>>() {
                    });
                    messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE_TO_CUSTOM,"",status, content,"影响场发送zip给消息服务","Map");
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }

    }
    private void scpFile( String localFilePath, String remoteFilePath){
        JSch jsch = new JSch();
        Session session = null;
        com.jcraft.jsch.Channel channel = null;
        try {
            // 创建 SSH 会话
            session = jsch.getSession("yingji", "10.5.92.112", 22);
            session.setPassword("CENC@dzj_88015563");
            // 避免 SSH 密钥检查提示
            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            // 连接会话
            session.connect();

            // 打开 SCP 通道
            channel = session.openChannel("exec");
            String command = "scp -t " + remoteFilePath;
            ((ChannelExec) channel).setCommand(command);

            // 连接通道
            channel.setInputStream(null);
            ((ChannelExec) channel).setErrStream(System.err);
            java.io.OutputStream out = channel.getOutputStream();
            java.io.InputStream in = channel.getInputStream();
            channel.connect();

            // 检查通道响应
            if (checkAck(in) != 0) {
                System.exit(0);
            }

            // 获取本地文件
            File localFile = new File(localFilePath);
            long fileSize = localFile.length();
            // 发送文件信息
            command = "C0644 " + fileSize + " ";
            if (localFilePath.lastIndexOf('/') > 0) {
                command += localFilePath.substring(localFilePath.lastIndexOf('/') + 1);
            } else {
                command += localFilePath;
            }
            command += "\n";
            out.write(command.getBytes());
            out.flush();

            // 再次检查通道响应
            if (checkAck(in) != 0) {
                System.exit(0);
            }

            // 发送文件内容
            FileInputStream fis = new FileInputStream(localFile);
            byte[] buf = new byte[1024];
            while (true) {
                int len = fis.read(buf, 0, buf.length);
                if (len <= 0) {
                    break;
                }
                out.write(buf, 0, len);
            }
            fis.close();

            // 发送结束符
            buf[0] = 0;
            out.write(buf, 0, 1);
            out.flush();

            // 最后检查通道响应
            if (checkAck(in) != 0) {
                System.exit(0);
            }
            out.close();
            System.out.println("文件传输成功");
        } catch (JSchException | IOException e) {
            System.err.println("文件传输失败: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 关闭通道和会话
            if (channel != null) {
                channel.disconnect();
            }
            if (session != null) {
                session.disconnect();
            }
        }
    }

    private int checkAck(InputStream in) throws IOException {
        int b = in.read();
        // b 可能为 0 表示成功，1 表示错误，2 表示致命错误，-1 表示结束
        if (b == 0) {
            return b;
        }
        if (b == -1) {
            return b;
        }

        if (b == 1 || b == 2) {
            StringBuilder sb = new StringBuilder();
            int c;
            do {
                c = in.read();
                sb.append((char) c);
            } while (c != '\n');
            if (b == 1) {
                System.out.print(sb.toString());
            }
            if (b == 2) {
                System.out.print(sb.toString());
            }
        }
        return b;
    }
    private static String createDateMkdir(StringBuilder mkdirPath){
        Calendar date = Calendar.getInstance();
        int month = date.get(Calendar.MONTH)+1;
        DecimalFormat df = new DecimalFormat("00");
        String formattedMonth = df.format(month);
        mkdirPath.append(date.get(Calendar.YEAR)).append("/").append(formattedMonth).append("/").append(date.get(Calendar.DAY_OF_MONTH));
//        return date.get(Calendar.YEAR)
//                + File.separator + (date.get(Calendar.MONTH)+1) + File.separator
//                + date.get(Calendar.DAY_OF_MONTH);
         return "";

    }

    //根据2点经纬度查询连线与正东方向的夹角，[0,180]
    private String getAngleByPoints(String point1,String point2){
        String angle = null;
        if (ObjectUtils.isNotEmpty(point1) && ObjectUtils.isNotEmpty(point2)
                && point1.contains("POINT(") && point2.contains("POINT(")) {
            String temp1LonLat = point1.replace("POINT(","");
            temp1LonLat = temp1LonLat.replace(")","");
            String[] temp1LonLatArr = temp1LonLat.split(" ");
            String temp2LonLat = point2.replace("POINT(","");
            temp2LonLat = temp2LonLat.replace(")","");
            String[] temp2LonLatArr = temp2LonLat.split(" ");
            if(temp1LonLatArr.length==2 && temp2LonLatArr.length==2){
                double temp1Lon = Double.parseDouble(temp1LonLatArr[0]);
                double temp1Lat = Double.parseDouble(temp1LonLatArr[1]);
                double temp2Lon = Double.parseDouble(temp2LonLatArr[0]);
                double temp2Lat = Double.parseDouble(temp2LonLatArr[1]);
                //取纬度小的为P2
                if (temp1Lat > temp2Lat) {
                    String P1LonLat = temp1LonLat;
                    String P2LonLat = temp2LonLat;
                    //P3为P2同纬度，经度增加1度的点
                    String P3LonLat = (temp2Lon + 1) + " " + temp2Lat;
                    //查询P1P2P3夹角,如果angle值大于180则夹角为360-angle，否则夹角为angle，夹角范围为[0,180]
                    angle = queryP1P2P3Angle(P1LonLat, P2LonLat, P3LonLat);
                } else {
                    String P1LonLat = temp2LonLat;
                    String P2LonLat = temp1LonLat;
                    //P3为P2同纬度，经度增加1度的点
                    String P3LonLat = (temp1Lon + 1) + " " + temp1Lat;
                    //查询P1P2P3夹角,如果angle值大于180则夹角为360-angle，否则夹角为angle，夹角范围为[0,180]
                    angle = queryP1P2P3Angle(P1LonLat, P2LonLat, P3LonLat);
                }
            }
        }

        return angle;
    }
    public String queryP1P2P3Angle(String P1LonLat, String P2LonLat, String P3LonLat) {
        String angle = null;
        try {
            if (ObjectUtils.isNotEmpty(P1LonLat) && ObjectUtils.isNotEmpty(P2LonLat) && ObjectUtils.isNotEmpty(P3LonLat)) {
                String sql = "SELECT degrees(ST_Angle(st_geometryfromtext('Point(" + P1LonLat + ")',4490)," +
                        "st_geometryfromtext('Point(" + P2LonLat + ")',4490)," +
                        "st_geometryfromtext('Point(" + P3LonLat + ")',4490)))";
                /*//查询目标点相对于原点的方位角，方位角是从正Y轴(几何图形)或北子午线(地理位置)参考的正顺时针角度
                String sql = "SELECT degrees(ST_Azimuth(st_transform(ST_GeomFromText('Point(" + P2LonLat + ")',4490),2415)," +
                        "st_transform(ST_GeomFromText('Point(" + P3LonLat + ")',4490),2415)))";//投影到平面坐标系*/
                String degrees = jdbcTemplate.queryForObject(sql, String.class);
                if (ObjectUtils.isNotEmpty(degrees)) {
                    double angleNumber = Double.parseDouble(degrees);
                    if (angleNumber >= 0 && angleNumber <= 180) {
                        angle = String.valueOf(angleNumber);
                    } else if (angleNumber > 180 && angleNumber < 360) {
                        angleNumber = 360 - angleNumber;
                        angle = String.valueOf(angleNumber);
                    }
                }
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }

        return angle;
    }
    @DSTransactional
    private Map<String,Object> createInfluence(EarthquakeModel earthquakeModel) throws Exception {

        Map<String,Object> resultMap = new HashMap<>();
        //地震匹配到了影响场模型才会创建影响场数据 否则不需去查附近的断层角度
        String angle = "";
        if(earthquakeModel.getModel()!=null){
            angle = getFaultAngle(earthquakeModel.getEarthQuake());
        }
        createInfluence(earthquakeModel,angle,resultMap);
        return resultMap;
    }
    @RabbitHandler
    //@RabbitListener(queues = {"queue_influence"}, ackMode = "MANUAL")
    public void consumeEarthQuakeModel(Message message, Channel channel, EarthquakeModel earthquakeModel) throws Exception {
        log.info("收到消息了，开始生成影响场");
        CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
            log.info("收到消息了，正式开始生成影响场");
            //        //1、自动生成 2 重新生成  3、修正   4、导入
//        int type = earthquakeModel.getType();
            //求断层的角度来作为生成影响场的角度
            String dataSourceKey = earthquakeModel.getDataSource();
            Map<String,Object> resultMap = null;
            List<SettingSeismicInfluenceflied> influenceData = null;
            try{
                if(StringUtils.isNotBlank(dataSourceKey)){
                    // 切换到省份数据源
                    DynamicDataSourceContextHolder.push(dataSourceKey);
                }
                resultMap = createInfluence(earthquakeModel);
                //手动ack消费消息
                try {
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                influenceData = (List<SettingSeismicInfluenceflied>) resultMap.get("influenceData");
                List<LineSettingSeismicInfluenceflied> lineInfluenceData = (List<LineSettingSeismicInfluenceflied>) resultMap.get("lineFluenceData");
                //影响场数据集合
                if(influenceData.size()>0){
                    //保存影响场数据
                    saveBatch(influenceData);
                    //影响场设置为线型用于出图用
                    lineInfluenceData.forEach(entity->{
                        lineInfluenceMapper.insert(entity);
                    });
                    List<SettingSeismicInfluenceflied> intensityData = (List<SettingSeismicInfluenceflied>) resultMap.get("intensityData");
                    //生成压缩文件并发送生成的文件去消息服务
                    if(ObjectUtils.isNotEmpty(intensityData) && intensityData.size()>0){
                        createAndSendZipToMessageService(intensityData,earthquakeModel);
                    }


                    //不管生没生成影响场都需要给响应级别发送消息
                    Integer maxIntensity = (Integer) resultMap.get("maxIntensity");
                    //发送消息去响应级别
                    String modelId = earthquakeModel.getModel()==null?"":earthquakeModel.getModel().getId();
                    sendMsgToResponseLevel(earthquakeModel.getEarthQuake(),modelId,maxIntensity);
                    //if(influenceData!=null && influenceData.size()>0){
                    //发送消息给人员伤亡评估计算
                    //if(ObjectUtils.isNotEmpty(resultMap.get("toEvaluateData"))){
                    Object toEvaluateData = resultMap.get("toEvaluateData");
                    ToEvaluateVO toEvaluateVO;
                    if(toEvaluateData == null){
                        //表示没有生成影响场 也要发送消息主要是经济损失那需要给报告发送消息 不管评估有没有结果都需要发消息给报告
                        toEvaluateVO = new ToEvaluateVO();
                        toEvaluateVO.setInfluenceList(new ArrayList<>());
                        toEvaluateVO.setEarthQuakeId(earthquakeModel.getEarthQuake().getId()+"");
                        toEvaluateVO.setInfluenceVersion(null);
                    }else{
                        toEvaluateVO =  (ToEvaluateVO)resultMap.get("toEvaluateData");
                    }

                    //if(toEvaluateVO.getInfluenceList()!=null){
                    toEvaluateVO.setDataSource(dataSourceKey);
                    toEvaluateVO.setEarthQuakeTime(earthquakeModel.getEarthQuake().getEarthquakeTime());
                    toEvaluateVO.setEarthType(earthquakeModel.getEarthQuake().getEarthquakeType());
                    toEvaluateVO.setPublish(earthquakeModel.getEarthQuake().getIsPublish());
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE_TO_EVALUATE,"",toEvaluateVO);
                    log.error("地震id{}--影响场给算法评估发送消息 || 成功,>>参数:{}",earthquakeModel.getEarthQuake().getId(),JSON.toJSONString(toEvaluateVO));
                    //}
                    //}
                    //发送消息去创建各烈度区面积、人口
                    sendMsgToCreateAreaPop(earthquakeModel.getEarthQuake().getId(),influenceData.get(0).getVersion(),earthquakeModel.getEarthQuake().getProvinceId(),earthquakeModel.getEarthQuake().getEarthquakeType());
                    //发送消息去创建不同烈度下的医院学校水库统计
                    sendMsgToCreateStatics(earthquakeModel.getEarthQuake().getId(),influenceData.get(0).getVersion(),earthquakeModel.getEarthQuake().getProvinceId(),earthquakeModel.getEarthQuake().getEarthquakeType());
                    //发送影响场消息给出图规则
                    String geomText = "POINT ("+earthquakeModel.getEarthQuake().getLongitude()+" "+earthquakeModel.getEarthQuake().getLatitude()+")";
                    try {
                        sendMsgToMapRule(influenceData,earthquakeModel.getEarthQuake(),earthquakeModel.getDataSource(),geomText);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                log.error("地震id"+earthquakeModel.getEarthQuake().getId()+"-- 创建影响场"+"|| 成功。>> 参数:"+JSON.toJSONString(earthquakeModel));
            }catch (Exception e){
                e.printStackTrace();
                String msgId = earthquakeModel.getEarthQuake().getId();
                log.error("{},---创建影响场||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(earthquakeModel));
//                String msgId = earthquakeModel.getEarthQuake().getId();
//                int retryCount = retryMap.getOrDefault(msgId, 0);
//                log.error("{},--创建影响场||失败,处理消息时发生错误:{},即将开始第{}次消息重试...",msgId,e.getMessage(),retryCount + 1, e);
//                if (retryCount >= failedRetry - 1) {
//                    log.error("{},---创建影响场||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(earthquakeModel));
//                    // 拒绝消息，并且不重新入队
//                    try {
//                        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.remove(msgId);
//                } else {
//                    // 重新发送消息到队列
//                    try {
//                        channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
//                                message.getMessageProperties().getReceivedRoutingKey(),
//                                MessageProperties.MINIMAL_PERSISTENT_BASIC,
//                                JSON.toJSONBytes(earthquakeModel));
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.put(msgId, retryCount + 1);
//                    log.error("{},--创建影响场||失败,消息重新入队,当前重试次数: {}", msgId,retryCount + 1);
//                }
            }finally {
                if(StringUtils.isNotBlank(dataSourceKey)){
                    DynamicDataSourceContextHolder.clear();
                }
            }

                //发送消息给报告
                //sendMsgToReport(earthquakeModel.getEarthQuake().getId(),earthquakeModel.getEarthQuake().getEarthquakeType(),dataSourceKey,earthquakeModel.getEarthQuake().getIsPublish(),influenceData.get(0).getVersion());
            //}
        },executor);

    }

    private Map<String,Object> getDataSourceKey(String dataSourceKey,String tableName){
        Map<String,Object> resultMap = new HashMap<>();
        int flag = 0;
        //先去cea库查询判断查询机场的数据库是公库还是专库
        DynamicDataSourceContextHolder.clear();
        DynamicDataSourceContextHolder.push("master");
        LambdaQueryWrapper<UsesetConfigDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(UsesetConfigDO::getId,UsesetConfigDO::getLibType,UsesetConfigDO::getDivisionCode,UsesetConfigDO::getTableName).eq(UsesetConfigDO::getTableName,tableName);
        List<UsesetConfigDO> usesetConfigDOList = usesetConfigMapper.selectList(lambdaQueryWrapper);
        if(ObjectUtils.isEmpty(usesetConfigDOList) || usesetConfigDOList.size() == 0){
            //查询专库
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push(dataSourceKey);
        }else{
            String divisionCode = StrUtil.removePrefix(dataSourceKey,"province_");
            List<UsesetConfigDO> collect = usesetConfigDOList.stream().filter(useset -> divisionCode.equals(useset.getDivisionCode())).collect(Collectors.toList());
            //存在地震所在省的数据
            if(ObjectUtils.isNotEmpty(collect) && collect.size()>0){
                UsesetConfigDO usesetConfigDO = collect.get(0);
                //libType 使用数据：（1 公用库， 2 专用库，3 只有专库）
                Integer libType = usesetConfigDO.getLibType();
                if(2 == libType){
                    // 2 == usesetConfigDO.getLibType() 表示公专两库都有存储但是选择了从专库查询
                    DynamicDataSourceContextHolder.clear();
                    DynamicDataSourceContextHolder.push("province_"+usesetConfigDO.getDivisionCode());
                    flag = 1;
                }else if(1 == libType){
                    //1 == usesetConfigDO.getLibType() 表示同时在公库和专库存储的但是选择了从公库查询
                    DynamicDataSourceContextHolder.clear();
                    DynamicDataSourceContextHolder.push("slave");
                    flag = 1;
                }else if(3 == libType){
                    // 3 == usesetConfigDO.getLibType() 表示数据只存专库且只查专库
                    DynamicDataSourceContextHolder.clear();
                    DynamicDataSourceContextHolder.push(dataSourceKey);
                    flag = 0 ;
                }
            }else{
                //不存在地震所在省的数据从专库查询
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("slave");
                flag = 0 ;
            }
        }
        resultMap.put("flag",flag);
        resultMap.put("dataSourceKey",DynamicDataSourceContextHolder.peek());
        return resultMap;
    }
    private List<DataAirPort>  getAirPortData(String geomText1,String geomText,int num){
        //查询某个烈度圈的机场信息
        return dataAirPortMapper.getData(geomText1, geomText, num);
    }

    //保存机场的统计数据
    private void saveAirPortData(String dataSourceKey,String earthQuakeId,String version,Integer num,List<DataAirPort> resultList){
        DynamicDataSourceContextHolder.clear();
        DynamicDataSourceContextHolder.push(dataSourceKey);
        for (DataAirPort dataAirPort : resultList) {
            InfluenceAirPort airPort = new InfluenceAirPort();
            airPort.setId(UUID.randomUUID().toString().replace("-",""))
                    .setEarthQuakeId(earthQuakeId).setVersion(version)
                    .setDistance(dataAirPort.getDistance()).setName(dataAirPort.getName()).setNum(num);
            influenceAirPortMapper.insert(airPort);
        }
    }
    //获取房屋格网数据
    private BigDecimal getHouseGridData(int asInt,int maxIntenisty,boolean flag,Map<String, SettingSeismicInfluenceflied> map){
        BigDecimal totalArea = BigDecimal.ZERO;
        for(;asInt<=maxIntenisty;asInt++){
            String geomText1 = map.get(asInt + "").getGeomText();
            //房屋有其他、砌体、钢混、单体四类房屋格网数据 需要分别计算求总
            List<DataHouseRebar> houseBarList = dataHouseRebarMapper.getByGeom(geomText1, "4490");
            if(ObjectUtils.isNotEmpty(houseBarList) &&  houseBarList.size()>0){
                flag = true;
                BigDecimal area = houseBarList.stream().map(DataHouseRebar::getHouse).reduce(BigDecimal.ZERO, BigDecimal::add);
                totalArea = totalArea.add(area);
            }
            List<DataHousedanceng> dataHousedancengList = dataHouseDancengMapper.getByGeom(geomText1, "4490");
            if(ObjectUtils.isNotEmpty(dataHousedancengList) &&  dataHousedancengList.size()>0){
                flag = true;
                BigDecimal area = dataHousedancengList.stream().map(DataHousedanceng::getHouse).reduce(BigDecimal.ZERO, BigDecimal::add);
                totalArea = totalArea.add(area);
            }
            List<DataHouseQita> qitaList = dataHouseQitaMapper.getByGeom(geomText1, "4490");
            if(ObjectUtils.isNotEmpty(qitaList) &&  qitaList.size()>0){
                flag = true;
                BigDecimal area = qitaList.stream().map(DataHouseQita::getHouse).reduce(BigDecimal.ZERO, BigDecimal::add);
                totalArea = totalArea.add(area);
            }
            List<DataHouseBrickwork> brickworkList = dataHouseBrickworkMapper.getByGeom(geomText1, "4490");
            if(ObjectUtils.isNotEmpty(brickworkList) &&  brickworkList.size()>0){
                flag = true;
                BigDecimal area = brickworkList.stream().map(DataHouseBrickwork::getHouse).reduce(BigDecimal.ZERO, BigDecimal::add);
                totalArea = totalArea.add(area);
            }

        }
        return totalArea;
    }
    //获取距离震中位置最近的5（最多5个）个机场数据
    private void  getFiveAirPortData(String geomText1,String geomText,int num,List<DataAirPort> resultList,int max,int min,Map<String, SettingSeismicInfluenceflied> map){
        while(true){
            List<DataAirPort> list = getAirPortData(geomText1,geomText,num);
            if(ObjectUtils.isNotEmpty(list) && list.size()>0){
                resultList.addAll(list);
            }
            if(resultList.size()==5){
                break;
            }else{
                //确定还有几个机场没找到
                num = num - list.size();
                max--;
                if(max>=min){
                    //如果没找到或找到的不足5个再在次一个烈度圈中找
                    geomText1 = map.get(max + "").getGeomText();
                }else{
                    break;
                }
            }
        }
    }
    @DSTransactional
    private void saveInfluenceOtherData(Integer minIntensity,String geomText, Map<String, SettingSeismicInfluenceflied> map,
                                        List<SettingSeismicInfluenceflied> influenceData,String earthQuakeId,String dataSourceKey,Integer maxIntenisty) throws ExecutionException, InterruptedException {
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(()->{
            if(minIntensity>=5){
                //判断机场数据到底在公库查询还是专库查询
                Map<String, Object> resultMap = getDataSourceKey(dataSourceKey, "data_airport");
                //计算机场信息
                //统计快速评估影响范围5度及以上区域机场数量，生成机场震中距数据，计算震中距离，最多列出5个，距离由近及远。
                int num = 5;
                int max = maxIntenisty,min = minIntensity;
                //先尝试在最大烈度中找距离震中位置最近的5个机场
                String geomText1 = map.get(max + "").getGeomText();
                List<DataAirPort> resultList = new ArrayList<>();
                //获取距离震中位置最近的5（最多5个）个机场数据
                getFiveAirPortData(geomText1,geomText,num,resultList,max,min,map);
                if(resultList.size()>0){
                    int airportNum = 0;
                    //查询5度范围内机场的个数
                    for(int i=5;i<=maxIntenisty;i++){
                        String geomText2 = map.get(i + "").getGeomText();
                        List<DataAirPortNum> data = dataAirPortNumMapper.getData(geomText2);
                        if(ObjectUtils.isNotEmpty(data) && data.size()>0){
                            airportNum+=data.get(0).getNum();
                        }
                    }
                    saveAirPortData(dataSourceKey,earthQuakeId,influenceData.get(0).getVersion(),airportNum,resultList);
                }else{
                    //没有获取距离震中最近的5个机场 也就是说该数据源中没有机场数据

                    //公专两库都有房屋格网数据但是查询的是专库没有数据的话查询公库
                    //只存专库 且没有查询到数据的话查询国家专库
                    if(1 == (int) resultMap.get("flag")){
                        if(!"slave".equals(DynamicDataSourceContextHolder.peek())){
                            //查询公库
                            DynamicDataSourceContextHolder.clear();
                            DynamicDataSourceContextHolder.push("slave");
                        }
                    }else{
                        //查询国家专库
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push("province_root");
                    }
                    num = 5;
                    max = maxIntenisty;
                    min = minIntensity;
                    geomText1 = map.get(max + "").getGeomText();
                    //获取距离震中位置最近的5（最多5个）个机场数据
                    getFiveAirPortData(geomText1,geomText,num,resultList,max,min,map);
                    if(resultList.size()>0){
                        int airportNum = 0;
                        //查询5度范围内机场的个数
                        for(int i=5;i<=maxIntenisty;i++){
                            String geomText2 = map.get(i + "").getGeomText();
                            List<DataAirPortNum> data = dataAirPortNumMapper.getData(geomText2);
                            if(ObjectUtils.isNotEmpty(data) && data.size()>0){
                                airportNum+=data.get(0).getNum();
                            }
                        }
                        saveAirPortData(dataSourceKey,earthQuakeId,influenceData.get(0).getVersion(),airportNum,resultList);
                    }
                }
                DynamicDataSourceContextHolder.clear();
            }
            System.out.println("---------------------计算机场线程完成");
            return 1;
        },executor);

        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(()->{
            //获取实际的大于6的最小烈度  兼容可能没有6度但是存在7度8度的这种
            OptionalInt min = influenceData.stream().map(SettingSeismicInfluenceflied::getDzIntensity).filter(value -> Double.parseDouble(value) >= 6).mapToInt(Integer::parseInt).min();
            if(min.isPresent()){
                //判断房屋数据到底在公库查询还是专库查询
                Map<String, Object> houseMap = getDataSourceKey(dataSourceKey, "data_houserebar");
                //房屋要查询的数据库
                String dataHouseDataSourceKey = DynamicDataSourceContextHolder.peek();
                //判断GDP数据到底在公库查询还是专库查询
                Map<String, Object> gdpMap = getDataSourceKey(dataSourceKey, "data_gdp");
                //房屋要查询的数据库
                String gdpDataSourceKey = DynamicDataSourceContextHolder.peek();

                //统计快速评估6度及以上区域房屋总面积
                //表示有最小值 则计算
                //int asInt = min.getAsInt();
                //切换房屋数据源查询数据
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push(dataHouseDataSourceKey);
                boolean flag = false;
                //List<DataHouseBar> houseList = new ArrayList<>();
                BigDecimal totalArea =  getHouseGridData(min.getAsInt(),maxIntenisty,flag,map);
                if(!flag){
                    //公专两库都有房屋格网数据但是查询的是专库没有数据的话查询公库
                    //只存专库 且没有查询到数据的话查询国家专库
                    if(1 == (int) houseMap.get("flag")){
                        if(!"slave".equals(DynamicDataSourceContextHolder.peek())){
                            //查询公库
                            DynamicDataSourceContextHolder.clear();
                            DynamicDataSourceContextHolder.push("slave");
                        }
                    }else{
                        //查询国家专库
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push("province_root");
                    }
                    totalArea =  getHouseGridData(min.getAsInt(),maxIntenisty,flag,map);
                }
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push(gdpDataSourceKey);
                //统计快速评估6度及以上区域总 GDP。
                List<DataGdp> gdps = new ArrayList<>();
                BigDecimal totalEconomics = getGdpData(min.getAsInt(), maxIntenisty, map,gdps);
                if(gdps.size() == 0){
                    //公专两库都有房屋格网数据但是查询的是专库没有数据的话查询公库
                    //只存专库 且没有查询到数据的话查询国家专库
                    if(1 == (int) gdpMap.get("flag")){
                        if(!"slave".equals(DynamicDataSourceContextHolder.peek())){
                            //查询公库
                            DynamicDataSourceContextHolder.clear();
                            DynamicDataSourceContextHolder.push("slave");
                        }
                    }else{
                        //查询国家专库
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push("province_root");
                    }
                    totalEconomics = getGdpData(min.getAsInt(), maxIntenisty, map,gdps);
                }
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push(dataSourceKey);
                InfluenceHouse influenceHouse = new InfluenceHouse();
                influenceHouse.setId(UUID.randomUUID().toString().replace("-","")).setArea(totalArea)
                        .setEarthQuakeId(earthQuakeId).setVersion(influenceData.get(0).getVersion()).setIntensity(min.getAsInt()+"");
                influenceHouseMapper.insert(influenceHouse);

                InfluenceGdp gdp = new InfluenceGdp();
                gdp.setId(UUID.randomUUID().toString().replace("-","")).setEconomics(totalEconomics)
                        .setEarthQuakeId(earthQuakeId).setVersion(influenceData.get(0).getVersion()).setIntensity(min.getAsInt()+"");
                influenceGdpMapper.insert(gdp);
            }
            DynamicDataSourceContextHolder.clear();
            System.out.println("---------------------计算房屋gdp线程完成");
            return 1;
        },executor);

        CompletableFuture.allOf(completableFuture1,completableFuture2).get();

    }

    private BigDecimal getGdpData(int min,int maxIntenisty,Map<String, SettingSeismicInfluenceflied> map, List<DataGdp> gdps){
        BigDecimal totalEconomics = BigDecimal.ZERO;
        for(int asInt = min;asInt<=maxIntenisty;asInt++){
            String geomText1 = map.get(asInt + "").getGeomText();
            //统计快速评估6度及以上区域总 GDP。
            List<DataGdp> dataGdps = dataGdpMapper.getByGeom1(geomText1, "4490");
            if(ObjectUtils.isNotEmpty(dataGdps) && dataGdps.size()>0){
                gdps.addAll(dataGdps);
                BigDecimal economics = dataGdps.stream().map(DataGdp::getEconomics).reduce(BigDecimal.ZERO, BigDecimal::add);
                totalEconomics = totalEconomics.add(economics);
            }
        }
        return totalEconomics;
    }
    //计算影响场每个烈度下的机场数量、房屋面积、GDP产值等信息
    private Map<String,Object> saveInfluenceOtherData(List<SettingSeismicInfluenceflied> influenceData, EarthQuake earthQuake,String dataSourceKey,String geomText) throws ExecutionException, InterruptedException {
        Map<String,Object> resultMap = new HashMap<>();
        Map<String, SettingSeismicInfluenceflied> map = influenceData.stream().collect(Collectors.toMap(SettingSeismicInfluenceflied::getDzIntensity, Function.identity()));
        //获取最大的烈度
        int maxIntenisty =  influenceData.stream().map(SettingSeismicInfluenceflied::getDzIntensity).mapToInt(Integer::parseInt).max().getAsInt();
        resultMap.put("maxIntensity",maxIntenisty);
        //最小烈度
        int minIntensity =  influenceData.stream().map(SettingSeismicInfluenceflied::getDzIntensity).mapToInt(Integer::parseInt).min().getAsInt();
        //保存指定烈度条件下的机场、房屋、人口、gdp等相关信息
        saveInfluenceOtherData(minIntensity,geomText,map,influenceData,earthQuake.getId(),dataSourceKey,maxIntenisty);
        //影响场最小烈度对应的id
        resultMap.put("influenceId",map.get(minIntensity+"").getUuid());
        return resultMap;
    }

    public void sendMsgToMapRule(List<SettingSeismicInfluenceflied> influenceData, EarthQuake earthQuake,String dataSourceKey,String geomText) throws ExecutionException, InterruptedException {
        Map<String,Object> toMapRule = new HashMap<>();
        Map<String,Object> resultMap = saveInfluenceOtherData(influenceData,earthQuake,dataSourceKey,geomText);
        System.out.println("--------------------------------------------------给图件规则发送消息");
        toMapRule.put("maxIntensity",resultMap.get("maxIntensity"));
        toMapRule.put("influenceId",resultMap.get("influenceId"));
        toMapRule.put("earthQuakeTitle",earthQuake.getTitle());
        toMapRule.put("earthQuakeLevel",earthQuake.getEarthquakeMagnitude()+"");
        toMapRule.put("earthQuakeType",earthQuake.getEarthquakeType());
        toMapRule.put("earthQuakeId",earthQuake.getId());
        toMapRule.put("latitude",earthQuake.getLatitude());
        toMapRule.put("longitude",earthQuake.getLongitude());
        toMapRule.put("dataSourceKey",dataSourceKey);
        toMapRule.put("publish",earthQuake.getIsPublish());
        toMapRule.put("influenceVersion",influenceData.get(0).getVersion());
        toMapRule.put("earthQuakeTime",DateUtil.format(earthQuake.getEarthquakeTime(),"yyyy-MM-dd HH:mm:ss"));
        toMapRule.put("province",earthQuake.getBelongToProvince());
        toMapRule.put("referenceLocation",earthQuake.getReferenceLocation());
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_PICTURE,toMapRule);
            log.error("地震id"+earthQuake.getId()+"-- 给图件规则发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(toMapRule));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_PICTURE,toMapRule);
                    flag = true;
                    log.error("地震id"+earthQuake.getId()+"-- 给图件规则发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(toMapRule));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+earthQuake.getId()+"-- 给图件规则发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(toMapRule));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toMapRule), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_PICTURE,status, content,"影响场发送消息出图规则","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    private void sendMsgToCreateStatics(String earthQuakeId, String version,String dataSourceKey,Integer earthQuakeType) {
        Map<String,Object> toCreateStatics = new HashMap<>();
        toCreateStatics.put("earthQuakeId",earthQuakeId);
        toCreateStatics.put("earthQuakeType",earthQuakeType);
        toCreateStatics.put("dataSourceKey",dataSourceKey);
        toCreateStatics.put("influenceVersion",version);
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_STATICS,toCreateStatics);
            log.info("------影响场给学校水库医院统计消息发送成功--------------"+toCreateStatics);
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_STATICS,toCreateStatics);
                    flag = true;
                    log.info("------影响场给学校水库医院统计消息发送成功--------------"+toCreateStatics);
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.info("------影响场给学校水库医院统计消息发送失败--------------");
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toCreateStatics), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_STATICS,status, content,"影响场发送消息去创建不同烈度下的医院学校水库统计","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }
    private void sendMsgToCreateAreaPop(String earthQuakeId, String version,String dataSourceKey,Integer earthQuakeType) {
        Map<String,Object> toCreateAreaPop = new HashMap<>();
        toCreateAreaPop.put("earthQuakeId",earthQuakeId);
        toCreateAreaPop.put("earthQuakeType",earthQuakeType);
        toCreateAreaPop.put("dataSourceKey",dataSourceKey);
        toCreateAreaPop.put("influenceVersion",version);
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_AREA_POP,toCreateAreaPop);
            log.info("------影响场给创建影响场面积人口消息发送成功--------------"+toCreateAreaPop);
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_AREA_POP,toCreateAreaPop);
                    flag = true;
                    log.info("------影响场给创建影响场面积人口消息发送成功--------------"+toCreateAreaPop);
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.info("------影响场给创建影响场面积人口消息发送失败--------------");
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toCreateAreaPop), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_AREA_POP,status, content,"影响场发送消息去创建各烈度区面积、人口","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    private void sendMsgToReport(String id,Integer earthQuakeType,String dataSourceKey,Boolean publish,String version)  {
        Map<String,Object> toReportMap = new HashMap<>();
        toReportMap.put("earthQuakeId",id);
        toReportMap.put("earthQuakeType",earthQuakeType);
        toReportMap.put("dataSourceKey",dataSourceKey);
        toReportMap.put("publish",publish);
        toReportMap.put("influenceVersion",version);
        //1 是自动触发生成的  2是手动重新计算的影响场
        toReportMap.put("influenceType","1");
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,toReportMap);
            log.error("地震id"+id+"-- 影响场给报告发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(toReportMap));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,toReportMap);
                    flag = true;
                    log.error("地震id"+id+"-- 影响场给报告发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(toReportMap));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+id+"-- 影响场给报告发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(toReportMap));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toReportMap), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,status, content,"影响场发送消息给报告","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }


    //创建shp压缩文件
    public Double createShpDataFile(List<SettingSeismicInfluenceflied> intensityList,String name,String zipPath) throws Exception {
        String path = localDir + "/" + name + ".shp";

        buildData(intensityList,path);
        InputStream input = null;
        ZipOutputStream zipOut = null;

        File zipFile = new File(zipPath);
        try {
            zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            // zip的名称为
            zipOut.setComment(name);
            String[] shpFiles = new String[]{
                    localDir + File.separator + name + ".dbf",
                    localDir + File.separator + name + ".prj",
                    localDir + File.separator + name + ".shp",
                    localDir + File.separator + name + ".shx",
                    localDir + File.separator + name + ".fix"
            };
            for (int i = 0; i < shpFiles.length; i++) {
                File file1 = new File(shpFiles[i]);
                input = new FileInputStream(file1);
                zipOut.putNextEntry(new ZipEntry(file1.getName()));
                int temp = 0;
                while ((temp = input.read()) != -1) {
                    zipOut.write(temp);
                }
            }
            for (String shpFile : shpFiles) {
                //删除生成的临时文件
                File file1 = new File(shpFile);
                file1.deleteOnExit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                input.close();
            }
            if (zipOut != null) {
                zipOut.close();
            }

        }
        //uploadFile(zipFile.getAbsolutePath(),absolutePath);
        //scpFile("/data/file/20211030130803.zip","/data/file/202110301308031.zip");
        return BigDecimal.valueOf(zipFile.length()).divide(BigDecimal.valueOf(1000),2,RoundingMode.HALF_DOWN).doubleValue();
    }

    private void buildData(List<SettingSeismicInfluenceflied> intensityList, SimpleFeatureTypeBuilder tb, ShapefileDataStore ds) throws IOException {
//        File file = new File(path);
//
//        ShapefileDataStoreFactory sf = new ShapefileDataStoreFactory();
//        ShapefileDataStore ds = (ShapefileDataStore) sf.createDataStore(params);
//        ds.setCharset(Charset.forName("GBK"));
//        SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
//        tb.setCRS(CRS.decode("EPSG:4490"));
//        tb.setName("shapefile");
//        tb.add("INTENSITY", String.class);
//        tb.add("INTENSHOW", String.class);
//        tb.add("the_geom", MultiPolygon.class);
//        SimpleFeatureType simpleFeatureType = tb.buildFeatureType();
//        ds.createSchema(simpleFeatureType);
//        FeatureWriter featureWriter = ds.getFeatureWriter(ds.getTypeNames()[0], null);
//        for (SettingSeismicInfluenceflied entity : intensityList) {
//            SimpleFeature feature = (SimpleFeature) featureWriter.next();
//            feature.setAttribute(1, entity.getDzIntensity());
//            feature.setAttribute(2, intensityMap().get(entity.getDzIntensity()));
//            feature.setAttribute("the_geom", entity.getGeom());
//        }
//        featureWriter.write();
//        featureWriter.close();
//        ds.dispose();
    }

    private Map<String,String> intensityMap(){
        Map<String,String> map = new HashMap<>(10);
        map.put("5","V");
        map.put("6","Ⅵ");
        map.put("7","Ⅶ");
        map.put("8","Ⅷ");
        map.put("9","Ⅸ");
        map.put("10","Ⅹ");
        map.put("11","Ⅺ");
        map.put("12","Ⅻ");
        map.put("13","XIII");
        map.put("14","XIV");
        return map;
    }

    //创建椭圆地震影响场
    public Map<String,Object> createInfluenceEllipse(Double lon,Double lat,Double longX,Double shortY,String angle,String minLongX,String minShortY){
        Map<String,Object> map = new HashMap<>();
        Double area = null;
        String result = "";
        try {
            //经度
            double x = lon;
            //纬度
            double y = lat;
            //长轴（米）
            double macroaxis = longX * 1000;
            //短轴（米）
            double brachyaxis = shortY * 1000;
            double v = (macroaxis / 2) * (brachyaxis / 2);
            area = 3.14 * v / 1000000;
            //旋转角度
            double direction =  Double.parseDouble(angle);
            //创建椭圆
            Polygon ellipse = createEllipse(x,y,macroaxis,brachyaxis,direction);
            //内圈椭圆
            if(StringUtils.isNotBlank(minLongX) && StringUtils.isNotBlank(minShortY)){
                //内圈长轴（米）
                double min_macroaxis = Double.parseDouble(minLongX) * 1000;
                //内圈短轴（米）
                double min_brachyaxis = Double.parseDouble(minShortY) * 1000;
                //创建内圈椭圆
                Polygon innerEllipse = createEllipse(x,y,min_macroaxis,min_brachyaxis,direction);
//                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
//                // 投影转换
//                MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
                result = ellipse.toString() + ";" + innerEllipse.toString();
//                WKTReader wktReader = new WKTReader();
                result = result.replace("));POLYGON ((","), (");
//                //读取wkt为Geometry 几何对象
//                org.locationtech.jts.geom.Geometry geom = wktReader.read(result);
//                area = JTS.transform(geom, transform).getArea()/1000000;
            }else{//无内圈椭圆
                //返回结果
//                double area2 = ellipse.getArea();
//                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
//                // 投影转换
//                MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
//                double area1 = JTS.transform(ellipse, transform).getArea();
//                area = JTS.transform(ellipse, transform).getArea()/1000000;
                result = ellipse.toString();
            }

        } catch (Exception e2) {
            e2.printStackTrace();
        }
        map.put("result",result);
        map.put("area",area);
        return map;
    }

    //创建椭圆地震影响场
    public Map<String,Object> createInfluenceCircle(Double lon,Double lat,Double radius,Double shortRadius){
        Map<String,Object> map = new HashMap<>();
        Double area = null;
        String result = "";
        try {
            //经度
            double x = lon;
            //纬度
            double y = lat;
            area = 3.14 * radius * radius;
            //创建圆
            Polygon ellipse = createCircle(x,y,radius);
            //内圈圆
            if(ObjectUtils.isNotEmpty(shortRadius) ){
                //创建内圈椭圆
                Polygon innerEllipse = createCircle(x,y,shortRadius);
//                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
//                // 投影转换
//                MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
                result = ellipse.toString() + ";" + innerEllipse.toString();
                result = result.replace("));POLYGON ((","), (");
//                WKTReader wktReader = new WKTReader();
//                //读取wkt为Geometry 几何对象
//                org.locationtech.jts.geom.Geometry geom = wktReader.read(result);
//                area = JTS.transform(geom, transform).getArea()/1000000;
            }else{//无内圈椭圆
//                //返回结果
//                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
//                // 投影转换
//                MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
//                area = JTS.transform(ellipse, transform).getArea()/1000000;
                result = ellipse.toString();
            }

        } catch (Exception e2) {
            e2.printStackTrace();
        }
        map.put("result",result);
        map.put("area",area);
        return map;
    }
    /**
     * 根据中心点经纬度、长轴、短轴、角度生成椭圆
     * @param x
     * @param y
     * @param macroaxis
     * @param brachyaxis
     * @param direction
     * @return
     */
    public Polygon createEllipse(double x,double y,double macroaxis,double brachyaxis,double direction){
        //将长短轴转换为度数
        double macroaxisDegree = parseXLengthToDegree(y,macroaxis);
        double brachyaxisDegree = parseYLengthToDegree(y,brachyaxis);
        //将夹角转换为弧度
        double radians = Math.toRadians(direction);
        // 创建 GeometryFactory
        GeometryFactory geometryFactory = new GeometryFactory();
        // 创建中心点
        Coordinate center = new Coordinate(x, y);
        Point centerPoint = geometryFactory.createPoint(center);
        //生成工厂类
        GeometricShapeFactory shapeFactory = new GeometricShapeFactory(geometryFactory);
        //设置中心点
        shapeFactory.setCentre(new Coordinate(x,y));
        //设置长轴长度
        shapeFactory.setWidth(macroaxisDegree);
        //设置短轴长度
        shapeFactory.setHeight(brachyaxisDegree);
        //设置长轴和X轴夹角
        shapeFactory.setRotation(radians);
        //生成椭圆对象
        Polygon ellipse = shapeFactory.createEllipse();
        return ellipse;
    }

    /**
     * 根据中心点经纬度、半径生成圆
     * @param x
     * @param y
     * @param radius
     * @return
     */
    public Polygon createCircle(double x,double y,double radius){
        radius = parseYLengthToDegree(y,radius);
        //生成工厂类
        GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
        //设置中心点
        shapeFactory.setCentre(new Coordinate(x,y));
        shapeFactory.setNumPoints(32);
        shapeFactory.setCentre(new Coordinate(x, y));
        shapeFactory.setSize(radius * 2);
        //生成椭圆对象
        return shapeFactory.createCircle();
    }
    // 地球赤道半径（单位：米）
    private static final double EARTH_SEMI_MAJOR_AXIS  = 6378137;
    // 地球极半径（单位：米）
    private static final double EARTH_SEMI_MINOR_AXIS  = 6356752;
    /**
     * 根据所在纬度，将X轴的长度（米）转换成经度
     * （因为不同纬度下，1°经度代表的长度不同）
     * @param latitude 所在纬度
     * @param length 线段长度
     * @return
     */
    public static double parseXLengthToDegree(double latitude,double length){
//        //计算当前纬度地球周长
//        double latPEarth = P_EARTH * Math.cos(latRadian);
//        //将length长度转换为度数
//        double xDegree = length / latPEarth * 360;
//        return xDegree;
        // 计算该纬度处的周长
        double circumference = calculateCircumferenceAtLatitude(latitude);
        // 计算长度对应的角度
        return (length / circumference) * 360;
    }


    //计算指定纬度处的地球周长
    private  static double calculateCircumferenceAtLatitude(double latitude) {
        // 将纬度转换为弧度
        double latRad = Math.toRadians(latitude);
        // 计算第一偏心率
        double eccentricity = Math.sqrt(1 - (EARTH_SEMI_MINOR_AXIS * EARTH_SEMI_MINOR_AXIS) / (EARTH_SEMI_MAJOR_AXIS * EARTH_SEMI_MAJOR_AXIS));
        // 计算卯酉圈曲率半径
        double primeVerticalRadius = EARTH_SEMI_MAJOR_AXIS / Math.sqrt(1 - eccentricity * eccentricity * Math.sin(latRad) * Math.sin(latRad));
        // 计算该纬度处纬线的半径
        double radiusAtLatitude = primeVerticalRadius * Math.cos(latRad);
        // 计算周长
        return 2 * Math.PI * radiusAtLatitude;
    }

    /**
     * 将Y轴的长度（米）转换成纬度
     * @param length
     * @return
     */
    public double parseYLengthToDegree(double latitude,double length){
        //将length长度转换为度数
        //return length / P_EARTH * 360;
        return length /calculateCircumferenceAtLatitude(latitude)* 360;
    }

    public List<InfluenceTitleVO> currentEarthInfluence(String earthId,String current,String divisionCode) {
        List<InfluenceTitleVO> resultList = new ArrayList<>();
        List<SettingSeismicInfluenceflied> list = null;
        if("1".equals(current)){
            //查询当前地震影响场
            list = settingInfluenceMapper.selectListByConditionCurrent(earthId);
        }else{
            list = settingInfluenceMapper.selectListByCondition(earthId);
        }
        try{
            if(ObjectUtils.isNotEmpty(list)){
                list.forEach(entity->{
                    InfluenceTitleVO vo = new InfluenceTitleVO();
                    Integer type = entity.getType();
                    String version = entity.getVersion();
                    StringBuilder name = new StringBuilder();
                    // 1 自动生成  2 重新生成  3、修正  4、导入
                    if(1 == type){
                        name.append("【自动生成】");
                    }else if(2 == type){
                        name.append("【重新生成 】");
                    }else if(3 == type){
                        name.append("【修正】");
                    }else if(4 == type){
                        name.append("【导入】");
                    }
                    name.append(version);
                    vo.setVersion(version)
                            .setValue(name.toString());
                    resultList.add(vo);
                });
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return resultList;
    }

    /**
     * 根据地震事件、影响场查询关联的影响场烈度信息
     */
    @DS("slave")
    public void currentEarthInfluenceForExport(String earthId, String version, Integer type, String flag, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String code = request.getHeader("divisionCode");
        String divisionCode = code.split("_")[0];
        //1--正式地震  2--测试地震  3--演练地震  4--自动地震, 默认是2 测试地震
        EarthQuake earthQuake = null;
        try{
            if("2".equals(flag) || "3".equals(flag)){
                //正式和自动的地震默认查询公共库，但是测试和演练的地震去各自专用库中查询地震信息
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            earthQuake = earthQuakeInfluenceService.getById(earthId);
            if("1".equals(flag) || "4".equals(flag)){
                //正式和自动的地震查询的是公共库，但是影响场信息保存在各自的专库中
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            List<SettingSeismicInfluenceflied> list = settingInfluenceMapper.selectInfluence(earthId,version);

            //String fileName =  getEarthTypePrefixName(earthQuake.getEarthquakeType());
            String title = earthQuake.getTitle();
//            int index = title.lastIndexOf(":");
//            if(index>0){
//                index = index+3;
//            }
//            title = title.substring(index);
            if (1==type) {
                //导出为shp文件
                String name = title;
                String zipPath = localDir + File.separator + name + ".zip";
                createShpDataFile(list,name,zipPath,response);
            }else if (2==type) {
                /**
                 * {
                 * 	"type": "FeatureCollection",
                 * 	"crs": {
                 * 		"type": "name",
                 * 		"properties": {
                 * 			"name": "EPSG:4326"
                 *                }* 	},
                 * 	"features": [{
                 * 		"type": "Feature",
                 * 		"properties": {
                 * 			"intensity": 7,
                 * 			"intensity_show": "\u2166"
                 * 		},
                 * 		"geometry": {
                 * 			"type": "MultiPolygon",
                 * 			"coordinates": [
                 * 				[
                 * 					[
                 * 						[86.4676471025206, 34.089598789462286],
                 * 						[86.46707333297078, 34.08879149363703],
                 */
                GeoJson geoJson = new GeoJson();
                geoJson.setType("FeatureCollection");
                Crs crs = new Crs();
                crs.setType("name");
                Crs.Properties crsProperties = new Crs.Properties();
                crsProperties.setName("EPSG:4490");
                crs.setProperties(crsProperties);
                geoJson.setCrs(crs);
                List<InfluenceFeature> features = new ArrayList<>();
                for (SettingSeismicInfluenceflied influenceflied : list) {
                    InfluenceFeature feature = new InfluenceFeature();
                    feature.setType("Feature");
                    InfluenceFeature.Properties properties = new InfluenceFeature.Properties();
                    properties.setIntensity(Integer.parseInt(influenceflied.getDzIntensity()));
                    properties.setIntensity_show(intensityMap().get(influenceflied.getDzIntensity()));
                    feature.setProperties(properties);
                    InfluenceGeometry geometry = new InfluenceGeometry();
                    geometry.setType("MultiPolygon");
                    List<List<List<List<String>>>> coordList = new ArrayList<>();
                    List<List<List<String>>> coordList1 = new ArrayList<>();
                    List<List<String>> coordList2 = new ArrayList<>();
                    String geomText = influenceflied.getGeomText();
                    //POLYGON((102.91730790997782 34.3218277987891,102.91709026627446 34.3219317368265,102.9168546726405 34.322002686747965))
                    geomText = geomText.replace("POLYGON((","").replace("))","");
                    String[] coordinates = geomText.split(",");
                    for (String coordinate : coordinates) {
                        //86.4676471025206, 34.089598789462286
                        coordinate = coordinate.replace(" ",",");
                        List<String> coordList3 = new ArrayList<>();
                        coordList3.add(coordinate);
                        coordList2.add(coordList3);
                    }
                    coordList1.add(coordList2);
                    coordList.add(coordList1);
                    geometry.setCoordinates(coordList);
                    feature.setGeometry(geometry);
                    features.add(feature);
                }
                geoJson.setFeatures(features);
                try {
                    String name = title;
                    String fileAbsPath = localDir+File.separator+name+".geojson";
                    ObjectMapper objectMapper = new ObjectMapper(); // 创建ObjectMapper
                    objectMapper.writeValue(new File(fileAbsPath), geoJson); // 写入文件
                    System.out.println("GeoJSON文件已导出到:"+fileAbsPath);
                    //拼接下载默认名称并转为ISO-8859-1格式
                    String tempFileName = new String((name+".geojson").getBytes(), "ISO-8859-1");
                    response.setHeader("Content-Disposition", "attchment;filename=" + tempFileName);
                    response.setHeader("Access-Control-Allow-Origin", "*");
                    response.setHeader("Access-Control-Allow-Method", "POST,GET");
                    //该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
                    ServletOutputStream outputStream = response.getOutputStream();
                    FileInputStream inputStream = new FileInputStream(fileAbsPath);
                    // copy方法为文件复制,在这里直接实现了下载效果
                    IOUtils.copy(inputStream, outputStream);
                    // 关闭输入流
                    inputStream.close();
                } catch (Exception e) {
                    e.printStackTrace(); // 打印异常信息
                }
            }
        }catch (Exception e){
            throw new RuntimeException("导出失败");
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    private void buildData(List<SettingSeismicInfluenceflied> intensityList,String filePath) throws Exception {
        File file = new File(filePath);
        ShapefileDataStoreFactory sf = new ShapefileDataStoreFactory();
        ShapefileDataStore ds = (ShapefileDataStore) sf.createDataStore(file.toURI().toURL());
        String code = intensityList.get(0).getCode();
        ds.setCharset(Charset.forName("GBK"));
        SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
        tb.setCRS(CRS.decode("EPSG:4490"));
        tb.setName("shapefile");
        tb.add("INTENSITY", String.class);
        tb.add("INTENSHOW", String.class);
        tb.add("the_geom", MultiPolygon.class);
        SimpleFeatureType simpleFeatureType = tb.buildFeatureType();
        ds.createSchema(simpleFeatureType);
        FeatureWriter featureWriter = ds.getFeatureWriter(ds.getTypeNames()[0], null);
        int i = 1;
        for (SettingSeismicInfluenceflied entity : intensityList) {
            SimpleFeature feature = (SimpleFeature) featureWriter.next();
            feature.setAttribute(i++, entity.getDzIntensity());
            feature.setAttribute(i, intensityMap().get(entity.getDzIntensity()));
            String geom = "";
            if(entity.getGeom().contains("POLYGON")){
                geom = entity.getGeom().replace("SRID=4490;","");
            }else{
                geom = entity.getGeomText();
            }
            feature.setAttribute("the_geom", geom);
            i = 1;
        }
        featureWriter.write();
        featureWriter.close();
        ds.dispose();
    }
    //创建shp压缩文件
    public void createShpDataFile(List<SettingSeismicInfluenceflied> intensityList, String name, String zipPath, HttpServletResponse response) throws Exception {
        File zipFile = new File(zipPath);
        String zipName = zipFile.getName();
        if(zipName.contains(".zip")){
            zipName = zipName.replace(".zip","");
        }
        String path = localDir + File.separator + name + ".shp";
        buildData(intensityList,path);
        InputStream input = null;
        ZipOutputStream zipOut = null;

        try {
            zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            // zip的名称为
            zipOut.setComment(name);
            String[] shpFiles = new String[]{
                    localDir + File.separator + name + ".dbf",
                    localDir + File.separator + name + ".prj",
                    localDir + File.separator + name + ".shp",
                    localDir + File.separator + name + ".shx",
                    localDir + File.separator + name + ".fix"
            };
            for (int i = 0; i < shpFiles.length; i++) {
                File file1 = new File(shpFiles[i]);
                input = new FileInputStream(file1);
                zipOut.putNextEntry(new ZipEntry(file1.getName()));
                int temp = 0;
                while ((temp = input.read()) != -1) {
                    zipOut.write(temp);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (input != null) {
                input.close();
            }
            if (zipOut != null) {
                zipOut.close();
            }
            OutputStream os = null;
            InputStream is = null;
            try {

                // 防乱码
//                    String name =
//                        new String(realFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                response = requestAttributes.getResponse();
                assert response != null;
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(zipName, "UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                String absolutePath = zipFile.getAbsolutePath();
//                is = new FileInputStream("D:\\static\\【测试】四川少鸡汤5.4级地震.zip");
                is = new FileInputStream(zipFile);

                // PrintWrite pw=response.getWriter();  或
                os = response.getOutputStream();
                int flag = 0;
                while ((flag = is.read()) != -1) {
                    os.write(flag);
                }

            } catch (Exception e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
            } finally {
                try {
                    if (is != null) {
                        is.close();
                    }
                    if (os != null) {
                        os.flush();
                        os.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
//            try{
//                String zipName = zipFile.getName();
//                if(zipName.contains(".zip")){
//                    zipName = zipName.replace(".zip","");
//                }
//                String fileName = new String((zipName + ".zip").getBytes());
//                String newName = URLEncoder.encode(fileName, "GBK");
//                response.setHeader("Content-Disposition", "attchment;filename=" + newName);
//                response.setHeader("Access-Control-Allow-Origin", "*");
//                response.setHeader("Access-Control-Allow-Method", "POST,GET");
//                //该流不可以手动关闭,手动关闭下载会出问题,下载完成后会自动关闭
//                ServletOutputStream outputStream = response.getOutputStream();
//                FileInputStream inputStream = new FileInputStream(zipPath);
//                // copy方法为文件复制,在这里直接实现了下载效果
//                IOUtils.copy(inputStream, outputStream);
//                // 关闭输入流
//                inputStream.close();
//            }catch (Exception e){
//                e.printStackTrace();
//            }
        }
    }
    private String getEarthTypePrefixName(Integer earthquakeType){
        String prefixName = "";
        if(earthquakeType==2){
            //测试
            prefixName = "【测试】";
        }else if(earthquakeType==3){
            //演练
            prefixName = "【演练】";
        }
        return prefixName;
    }

    @DSTransactional
    public void createEarthQuakeInfluence(String earthQuakeId, int type,HttpServletRequest request) throws Exception{
        String code = request.getHeader("divisionCode");
        String divisionCode = code.split("_")[0];
        EarthquakeModel earthquakeModel = new EarthquakeModel();
        try{
            EarthQuake earthQuake = null;
            String faultAngle = "";
            if(1==type || 4==type){
                //正式或自动地震 查询公库
                DynamicDataSourceContextHolder.push("slave");
                earthQuake = earthQuakeInfluenceService.getById(earthQuakeId + "");
                if(earthQuake!=null){
                    faultAngle = getFaultAngle(earthQuake);
                }
                DynamicDataSourceContextHolder.clear();
                // 影响场保存在专库切换到省份数据源
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }else{
                // 切换到省份数据源
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
                earthQuake = earthQuakeInfluenceService.getById(earthQuakeId + "");
                DynamicDataSourceContextHolder.clear();
                // 切换到公库
                DynamicDataSourceContextHolder.push("slave");
                faultAngle = getFaultAngle(earthQuake);
                DynamicDataSourceContextHolder.clear();
                // 影响场保存在专库切换到省份数据源
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            Map<String, Object> resultMap = new HashMap<>();
            Model model = getModel(earthQuake);
            earthQuake.setEarthquakeType(type);
            earthquakeModel.setEarthQuake(earthQuake);
            earthquakeModel.setModel(model);
            earthquakeModel.setType(2);
            earthquakeModel.setDataSource(DynamicDataSourceContextHolder.peek());
            createInfluence(earthquakeModel,faultAngle,resultMap);
            if(ObjectUtils.isNotEmpty(resultMap.get("influenceData"))){
                List<SettingSeismicInfluenceflied> data = (List<SettingSeismicInfluenceflied>) resultMap.get("influenceData");
                if(data.size()>0){
                    saveBatch(data);
                    log.error("地震id"+earthQuake.getId()+"-- 创建影响场"+"|| 成功。>> 参数:"+JSON.toJSONString(earthquakeModel));
                }
                //保存影响场zip文件
                createInfluenceFile(earthQuake,data);
            }
        }catch (Exception e){
            log.error("地震id"+earthQuakeId+"-- 创建影响场"+"|| 失败。>> 参数:"+JSON.toJSONString(earthquakeModel));
            e.printStackTrace();
        }finally {
            DynamicDataSourceContextHolder.clear();
        }

    }
    private void createInfluenceFile(EarthQuake earthQuake,List<SettingSeismicInfluenceflied> intensityList) throws Exception {
        String name = earthQuake.getTitle()+"6度及以上影响场";
        StringBuilder mkdirPath = new StringBuilder("");
//            String mkdirPath = createDateMkdir(mkdirPath);
        createDateMkdir(mkdirPath);
        StringBuilder sb = new StringBuilder();
        String path = sb.append(filePath).append("/").append(mkdirPath).toString();
        if(!new File(path).exists()){
            new File(path).mkdir();
        }
        //表示存在烈度>=6度的，则需要生成shp文件推送给消息发送服务
        String zipPath = path +"/"+ name + ".zip";
        if(ObjectUtils.isNotEmpty(intensityList) || intensityList.size()>0){
            double size = createShpDataFile(intensityList,name,zipPath);
            //保存文件信息
            FileEntity fileDo = new FileEntity();
            //表示存在烈度>=6度的，则需要生成shp文件推送给消息发送服务
            //file.setConfigId(client.getId());
            fileDo.setName(name);
            fileDo.setFile(name + ".zip");
            fileDo.setMimeType("zip");
            fileDo.setEarthquakeId(earthQuake.getId());
            fileDo.setFileTypeId(3);
            fileDo.setConvertStatus(0);
            String divisionCode = earthQuake.getDivisionCode();
            LambdaQueryWrapper<DivisionManagerDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DivisionManagerDO::getDivisionCode,divisionCode);
            String divisionName = divisionManagerMapper.selectOne(lambdaQueryWrapper).getDivisionName();
            fileDo.setCreatedUser(divisionName);
            fileDo.setFilePath(File.separator+mkdirPath+File.separator+name + ".zip");
            fileDo.setSource(3);
            fileDo.setFileSize(size+"kb");
            fileDo.setEarthQuakeName(earthQuake.getTitle());
            fileDo.setProvince(earthQuake.getBelongToProvince());
            fileMapper.insert(fileDo);
        }
    }

    private Model getModel(EarthQuake earthQuake){
        Model model = null;
        //获取震级信息
        Double earthquakeMagnitude = earthQuake.getEarthquakeMagnitude();
        //经度
        Double longitude = earthQuake.getLongitude();
        //纬度
        Double latitude = earthQuake.getLatitude();
        //获取私有库中维护的影响场模型数据
        LambdaQueryWrapper<Model> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Model::getIsValid,"1");
        List<Model> models = modelMapper.selectList(lambdaQueryWrapper);
        if(ObjectUtils.isNotEmpty(models) && models.size()>0){
            //根据影响场的数据匹配触发条件中的震级范围获取符合触发条件的模型数据
            String geomText = "POINT("+ longitude+" "+latitude+")";
            return compareEarthQuakeLevel(models,earthquakeMagnitude+"",geomText);
        }else{
            String dataSourceKey = DynamicDataSourceContextHolder.peek();
            try{
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("slave");
                models = modelMapper.selectList(lambdaQueryWrapper);
                if(ObjectUtils.isNotEmpty(models) && models.size()>0){
                    //根据影响场的数据匹配触发条件中的震级范围获取符合触发条件的模型数据
                    String geomText = "POINT("+ longitude+" "+latitude+")";
                    model = compareEarthQuakeLevel(models,earthquakeMagnitude+"",geomText);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                DynamicDataSourceContextHolder.clear();
                //如果是查询的公库的模型数据但是后续的数据操作还需要操作各自对应库的，所以数据源需要切换回去
                DynamicDataSourceContextHolder.push(dataSourceKey);
            }
        }
        return model;
    }

    //比对震级范围 获取符合条件的模型
    private Model compareEarthQuakeLevel(List<Model> models,String earthquakeMagnitude, String geomText){
        List<Model> modelAllList = new ArrayList<>();
        BigDecimal magnitude = new BigDecimal(earthquakeMagnitude);
        for (Model model : models) {
            BigDecimal earthQuakeLevel1 = model.getEarthQuakeLevel1();
            BigDecimal earthQuakeLevel2 = model.getEarthQuakeLevel2();

            Boolean flag = false;
            //如果模型中的触发条件中的震级数据为空
            if(ObjectUtils.isNotEmpty(earthQuakeLevel1) || ObjectUtils.isNotEmpty(earthQuakeLevel2)){
                String earthQuakeLevelSymbol = model.getEarthQuakeLevelSymbol();
                String earthQuakeLevelSymbol1 = model.getEarthQuakeLevelSymbol1();
                if(ObjectUtils.isNotEmpty(earthQuakeLevel1)){
                    //最小值有值
                    //最小值震级范围符号   1 <=   2:<
                    if(ObjectUtils.isNotEmpty(earthQuakeLevel2)){
                        //最大值有值 //<=
                        if("1".equals(earthQuakeLevelSymbol)){
                            //<=
                            if("1".equals(earthQuakeLevelSymbol1)){
                                if(magnitude.compareTo(earthQuakeLevel1)>=0 && magnitude.compareTo(earthQuakeLevel2)<=0){
                                    flag = true;
                                }
                            }else if("2".equals(earthQuakeLevelSymbol1)){
                                if(magnitude.compareTo(earthQuakeLevel1)>=0 && magnitude.compareTo(earthQuakeLevel2)<0){
                                    flag = true;
                                }
                            }else if("3".equals(earthQuakeLevelSymbol1)){
                                if(magnitude.compareTo(earthQuakeLevel1)>=0 && magnitude.compareTo(earthQuakeLevel2)==0){
                                    flag = true;
                                }
                            }
                        }else  if("2".equals(earthQuakeLevelSymbol)){
                            //<=
                            if("1".equals(earthQuakeLevelSymbol1)){
                                if(magnitude.compareTo(earthQuakeLevel1)>0 && magnitude.compareTo(earthQuakeLevel2)<=0){
                                    flag = true;
                                }
                            }else if("2".equals(earthQuakeLevelSymbol1)){
                                if(magnitude.compareTo(earthQuakeLevel1)>0 && magnitude.compareTo(earthQuakeLevel2)<0){
                                    flag = true;
                                }
                            }else if("3".equals(earthQuakeLevelSymbol1)){
                                if(magnitude.compareTo(earthQuakeLevel1)>0 && magnitude.compareTo(earthQuakeLevel2)==0){
                                    flag = true;
                                }
                            }
                        }
                    }else{
                        //最大震级值无值 只需要比对最小震级值
                        if("1".equals(earthQuakeLevelSymbol)){
                            if(magnitude.compareTo(earthQuakeLevel1)>=0){
                                flag = true;
                            }
                        }else  if("2".equals(earthQuakeLevelSymbol)){
                            if(magnitude.compareTo(earthQuakeLevel1)>0 ){
                                flag = true;
                            }
                        }
                    }
                }else if(ObjectUtils.isNotEmpty(earthQuakeLevel2)){
                    //能进来表示最小震级值无值   只需要比较最大震级值即可
                    //<=
                    if("1".equals(earthQuakeLevelSymbol1)){
                        if(magnitude.compareTo(earthQuakeLevel2)<=0){
                            flag = true;
                        }
                    }else if("2".equals(earthQuakeLevelSymbol1)){
                        if(magnitude.compareTo(earthQuakeLevel2)<0){
                            flag = true;
                        }
                    }else if("3".equals(earthQuakeLevelSymbol1)){
                        if(magnitude.compareTo(earthQuakeLevel2)==0){
                            flag = true;
                        }
                    }
                }
            }
            if(!flag){
                continue;
            }
            //匹配适用区域
            Integer scope = model.getScope();
            if(null != scope){
                // 表示适用区域有维护
                List<Model> intersectsModel = modelMapper.getIntersectsModel(geomText, model.getId());
                if (ObjectUtils.isNotEmpty(intersectsModel) ){
                    modelAllList.addAll(intersectsModel);
                    break;
                }
            }
        }
        if(modelAllList.size()>0){
            return modelAllList.get(0);
        }
        return null;
    }
    //获取距离震中位置最近的活断层的角度则为生成的椭圆影响场的倾角
    private String getFaultAngle(EarthQuake earthQuake){
        //震中位置
        String centerGeom = "POINT ("+earthQuake.getLongitude()+" "+earthQuake.getLatitude()+")";
        //获取距离震中位置最近的断层
        ActiveFault activeFault = activeFaultService.getNearestFault(centerGeom);
        //求断层的角度来作为生成影响场的角度
        String angle = "";
        if (ObjectUtils.isNotEmpty(activeFault.getExtentText()) && activeFault.getExtentText().indexOf("BOX(") == 0 &&
                ObjectUtils.isNotEmpty(activeFault.getGeomText()) && activeFault.getGeomText().indexOf("LINESTRING(") != -1){
            //左下角到右上角的连线
            String boxExtent = activeFault.getExtentText();
            String lineString = boxExtent.replace("BOX","LINESTRING");
            //获取范围经纬度点
            String box = boxExtent.replace("BOX(", "").replace(")", "");
            String[] lonlatArr = box.split(",");
            String[] minLonLat = lonlatArr[0].split(" ");
            String[] maxLonLat = lonlatArr[1].split(" ");
            String minLon = minLonLat[0];
            String minLat = minLonLat[1];
            String maxLon = maxLonLat[0];
            String maxLat = maxLonLat[1];
            String geomText = activeFault.getGeomText();
            if(!geomText.contains(lonlatArr[0])){
                String[] testtest=geomText.replace("MULTILINESTRING((","").replace("))","").split(",");
                double xmin=0.0;
                double xmax=0.0;
                double ymin=0.0;
                double ymax=0.0;
                String[] source = testtest[0].split(" ");
                double xsource=Double.parseDouble(source[0]);
                double ysource=Double.parseDouble(source[1]);
                xmin=xsource;
                xmax=xsource;
                ymin=ysource;
                ymax=ysource;

                for(int i=1;i<testtest.length;i++){
                    String[] ss = testtest[i].split(" ");
                    String ss1=ss[0];
                    if(ss1.contains("(")){
                        ss1=ss[0].split("\\(")[1];
                    }
                    double x=Double.parseDouble(ss1);
                    String ss2=ss[1];
                    if(ss2.contains(")")){
                        ss2=ss[1].split("\\)")[0];
                    }
                    double y=Double.parseDouble(ss2);
                    if(ymin>y){
                        ymin=y;
                        xmin=x;
                    }
                    if(ymax<y){
                        ymax=y;
                        xmax=x;
                    }
                }
                if(xmax<xmin) {
                    //左上角
                    String leftTop = minLon + " " + maxLat;
                    //右下角
                    String rightBottom = maxLon + " " + minLat;
                    //左上角到右下角的连线
                    lineString = "LINESTRING(" + leftTop + "," + rightBottom + ")";
                }
            }

            //根据2点经纬度查询连线与正东方向的夹角，[0,180]）
            String[] points = lineString.replace("LINESTRING(","").replace(")", "").split(",");
            String point1 = "POINT(" + points[0] + ")";
            String point2 = "POINT(" + points[1] + ")";
            angle = getAngleByPoints(point1,point2);
        }
        return angle;
    }

    /**
     * 根据中心点经纬度、长轴、短轴、角度生成椭圆  包络图
     * @param x
     * @param y
     * @param macroaxis
     * @param brachyaxis
     * @param direction
     * @return
     */
    public Polygon createEnvelope(double x, double y, double macroaxis, double brachyaxis, double direction, double length){

        //将长短轴转换为度数
        double macroaxisDegree = parseXLengthToDegree(y,macroaxis);
        double brachyaxisDegree = parseYLengthToDegree(y,brachyaxis);
        //将夹角转换为弧度
        double radians = Math.toRadians(direction);
        //生成工厂类
        EnvelopeFactory shapeFactory = new EnvelopeFactory();
        //设置中心点
        shapeFactory.setCentre(new Coordinate(x,y));
        //设置长轴长度
        shapeFactory.setWidth(macroaxisDegree);
        //设置短轴长度
        shapeFactory.setHeight(brachyaxisDegree);
        //设置长轴和X轴夹角
        shapeFactory.setRotation(radians);
        //生成对象
        Polygon ellipse = shapeFactory.createEnvelope(length);
        return ellipse;
    }


    //创建椭圆地震影响场  包络图
    public Map<String,Object> createEnvelopeEllipse(Double lon,Double lat,Double longX,Double shortY,String angle,String minLongX,String minShortY,Double L){
        Map<String,Object> map = new HashMap<>();
        Double area = null;
        String result = "";
        try {
            //经度
            double x = lon;
            //纬度
            double y = lat;
            //长轴（米）
            double macroaxis = longX * 1000;
            //短轴（米）
            double brachyaxis = shortY * 1000;
            //破裂尺度（米）
            double length = L * 1000;
            //旋转角度
            double direction =  Double.parseDouble(angle);
            //创建椭圆
            Polygon ellipse = createEnvelope(x,y,macroaxis,brachyaxis,direction,length);
            //内圈椭圆
            if(StringUtils.isNotBlank(minLongX) && StringUtils.isNotBlank(minShortY)){
                //内圈长轴（米）
                double min_macroaxis = Double.parseDouble(minLongX) * 1000;
                //内圈短轴（米）
                double min_brachyaxis = Double.parseDouble(minShortY) * 1000;
                //创建内圈椭圆
                Polygon innerEllipse = createEnvelope(x,y,min_macroaxis,min_brachyaxis,direction,length);
                //area = innerEllipse.getArea();
                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
                // 投影转换
                MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
                result = ellipse.toString() + ";" + innerEllipse.toString();
                WKTReader wktReader = new WKTReader();
                result = result.replace("));POLYGON ((","), (");
                //读取wkt为Geometry 几何对象
                org.locationtech.jts.geom.Geometry geom = wktReader.read(result);
                area = JTS.transform(geom, transform).getArea()/1000000;
            }else{//无内圈椭圆
                //返回结果
                //返回结果
                CoordinateReferenceSystem crsTarget = CRS.decode("EPSG:3857");
                // 投影转换
                MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
                area = JTS.transform(ellipse, transform).getArea()/1000000;
                result = ellipse.toString();
            }

        } catch (Exception e2) {
            e2.printStackTrace();
        }
        map.put("result",result);
        map.put("area",area);
        return map;
    }


    @DSTransactional
    public String correctInfluence(Map<String, Object> map,HttpServletRequest request) throws Exception{
        List<SettingSeismicInfluenceflied> resultList = new ArrayList<>();
        List<LineSettingSeismicInfluenceflied> lineResultList = new ArrayList();
        String code = request.getHeader("divisionCode");
        String divisionCode = code.split("_")[0];
        String userId = code.split("_")[1];

        //地震类型
        String flag = (String) map.get("flag");
        List<LinkedHashMap> maps = (List<LinkedHashMap>) map.get("influence");
        List<InfluenceVO> vos = new ArrayList<>();
        if(ObjectUtils.isNotEmpty(maps) && maps.size()>0){
            for (LinkedHashMap linkedHashMap : maps) {
                InfluenceVO influenceVO = MapToEntityUtil.mapToEntity(linkedHashMap, InfluenceVO.class);
                vos.add(influenceVO);
            }
        }
        Map<String, InfluenceVO> intensityMap = vos.stream().collect(Collectors.toMap(InfluenceVO::getDzIntensity,Function.identity()));
        String earthQuakeId = vos.get(0).getEarthQuakeId();

        //1--正式地震  2--测试地震  3--演练地震  4--自动地震, 默认是2 测试地震
        EarthQuake earthQuake = null;
        try{
            if("2".equals(flag) || "3".equals(flag)){
                //正式和自动的地震默认查询公共库，但是测试和演练的地震去各自专用库中查询地震信息
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }else{
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("slave");
            }
            String peek = DynamicDataSourceContextHolder.peek();
            earthQuake = earthQuakeInfluenceService.getById(earthQuakeId);
            if("1".equals(flag) || "4".equals(flag)){
                //正式和自动的地震查询的是公共库，但是影响场信息保存在各自的专库中
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            log.error("地震id"+earthQuakeId+"-- 修正影响场"+"|| 开始。>> 参数:"+JSON.toJSONString(map));
            //震级
            BigDecimal earthquakeMagnitude = BigDecimal.valueOf(earthQuake.getEarthquakeMagnitude());
            //修正
            int[] intensityArr = vos.stream().map(InfluenceVO::getDzIntensity).mapToInt(Integer::parseInt).toArray();
            BigDecimal longX = BigDecimal.ZERO;
            BigDecimal shortY = BigDecimal.ZERO;
            boolean isNa = true;
            //最大烈度
            int i = Arrays.stream(intensityArr).max().getAsInt();
            String influenceVersion = DateUtil.format(DateUtil.date(), "yyyy-MM-dd HH:mm:ss");
            String category = intensityMap.get(String.valueOf(i)).getCategory();
            for(;i>=5;i--){
                //烈度
                int val = i;
                if(ObjectUtils.isNotEmpty(val)){
                    InfluenceVO influenceVO = intensityMap.get(String.valueOf(val));
                    SettingSeismicInfluenceflied influenceflied = new SettingSeismicInfluenceflied();
                    influenceflied.setEarthquakeLevel(earthquakeMagnitude);

                    //地震影响场烈度
                    influenceflied.setDzIntensity(String.valueOf(val));
                    influenceflied.setIntensityShow(intensityMap().get(String.valueOf(val)));
                    influenceflied.setIntensityChinaShow(IntensityUtil.getUpperNum(String.valueOf(val)));

                    influenceflied.setLongX(influenceVO.getLongAxis());
                    influenceflied.setShortY(influenceVO.getShortAxis());
                    //if(influenceVO.getLongAxis().equals(influenceVO.getShortAxis())){
                    if("1".equals(category)){
                        //圆
                        influenceflied.setCategory("1");
                        if (!isNa) {
                            //环
                            map = createInfluenceCircle(earthQuake.getLongitude(),
                                    earthQuake.getLatitude(),  influenceflied.getLongX().doubleValue(), longX.doubleValue());
                        } else {
                            //生成圆影响场
                            map = createInfluenceCircle(earthQuake.getLongitude(),
                                    earthQuake.getLatitude(), influenceflied.getLongX().doubleValue(), null);
                        }
                        influenceflied.setRuptureScale(BigDecimal.ZERO);
                    }else  if("2".equals(category)){
                        //椭圆
                        influenceflied.setCategory("2");
                        if (!isNa) {
                            //环
                            map = createInfluenceEllipse(earthQuake.getLongitude(),
                                    earthQuake.getLatitude(),  influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    String.valueOf(influenceVO.getAngle()), longX.toString(), shortY.toString());
                        } else {
                            //生成椭圆影响场
                            map = createInfluenceEllipse(earthQuake.getLongitude(),
                                    earthQuake.getLatitude(), influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    String.valueOf(influenceVO.getAngle()), null, null);
                        }
                        influenceflied.setRuptureScale(BigDecimal.ZERO);
                    }else{
                        //线源模型
                        //破裂尺度计算公式
                        //线源模型破裂尺度参数
                        BigDecimal L = influenceVO.getRuptureScale();
                        // 短轴：Ib=4.3517+ 1.2192M-3.7429Lg(Rb+6)
                        //式中，Ib分别为短轴烈度，M为震级，Rb分别为烈度为I时短半轴的长度
                        //根据公式计算得到Rb，如果值为负数，则舍掉，为正的则留下
                        //烈度为Ib时短半轴的长度
//                    //长轴长度
                        BigDecimal ra = influenceVO.getLongAxis();
//                    //短轴长度
                        BigDecimal rb = influenceVO.getShortAxis();
                        influenceflied.setLongX(ra);
                        influenceflied.setShortY(rb);
                        influenceflied.setCategory("3");
                        //生成线源影响场
                        if (!isNa) {
                            //环
                            map = createEnvelopeEllipse(earthQuake.getLongitude(),
                                    earthQuake.getLatitude(), influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    influenceVO.getAngle().toString(), longX.toString(), shortY.toString(),L.doubleValue());
                        }else{
                            map = createEnvelopeEllipse(earthQuake.getLongitude(),
                                    earthQuake.getLatitude(), influenceflied.getLongX().doubleValue(),
                                    influenceflied.getShortY().doubleValue(),
                                    influenceVO.getAngle().toString(), null, null,L.doubleValue());
                        }
                        influenceflied.setRuptureScale(L);
                    }
                    Double area = (Double) map.get("area");
                    String influenceEllipse = (String) map.get("result");
                    influenceflied.setUuid(UUID.randomUUID().toString().replace("-",""));
                    influenceflied.setEarthQuakeId(earthQuake.getId()+"");
                    isNa = false;
                    longX = influenceflied.getLongX();
                    shortY = influenceflied.getShortY();
                    PGgeometry pGgeometry = new PGgeometry(influenceEllipse);
                    Geometry geometry = pGgeometry.getGeometry();
                    geometry.setSrid(4490);
                    influenceflied.setGeom(geometry.toString());
                    influenceflied.setOperateUserId("");
                    influenceflied.setOperateDeptId("");
                    influenceflied.setOperateTime(new Date());
                    influenceflied.setTriggerType(earthQuake.getEarthquakeType());
                    influenceflied.setModelId("");
                    influenceflied.setDataSource(earthQuake.getEarthquakeType()+"");
                    influenceflied.setVersion(influenceVersion);
                    influenceflied.setType(3);
                    influenceflied.setCode(4490+"");
                    influenceflied.setArea(area);
                    influenceflied.setAngle(influenceVO.getAngle());
                    influenceflied.setRemark(earthQuake.getEarthquakeType()+"");
                    influenceflied.setOperateUserId(userId);
                    resultList.add(influenceflied);
                    String lineGeom = influenceEllipse;
                    // 查询外壳与资源关联数量
                    String sql = "SELECT ST_ExteriorRing('"+lineGeom+"')";
                    lineGeom = jdbcTemplate.queryForObject(sql, String.class);
                    LineSettingSeismicInfluenceflied lineSettingSeismicInfluenceflied = new LineSettingSeismicInfluenceflied();
                    BeanUtils.copyProperties(influenceflied,lineSettingSeismicInfluenceflied);
                    lineSettingSeismicInfluenceflied.setGeom(lineGeom);
                    lineResultList.add(lineSettingSeismicInfluenceflied);
                }
            }
            if(resultList.size()>0){
                saveBatch(resultList);
                createInfluenceFile(earthQuake,resultList);
                log.error("地震id"+earthQuakeId+"-- 修正影响场"+"|| 成功。>> 参数:"+JSON.toJSONString(map));
//                //计算影响场的机场、gdp、房屋面积
                String geomText = "POINT ("+earthQuake.getLongitude()+" "+earthQuake.getLatitude()+")";
                saveInfluenceOtherData(resultList,earthQuake,DynamicDataSourceContextHolder.peek(),geomText);
            }
            if(lineResultList.size()>0){
                lineResultList.forEach(entity->{
                    lineInfluenceMapper.insert(entity);
                });
            }

            return influenceVersion;
        }catch (Exception e){
            log.error("地震id"+earthQuakeId+"-- 修正影响场"+"|| 失败。>> 参数:"+JSON.toJSONString(map));
            e.printStackTrace();
        }finally {
            if(StringUtils.isNotBlank(DynamicDataSourceContextHolder.peek())){
                DynamicDataSourceContextHolder.clear();
            }
        }

        return "";
    }

    @DSTransactional
    public void importInfluence(Map<String, Object> map,HttpServletRequest request) throws Exception {
        List<SettingSeismicInfluenceflied> list = new ArrayList<>();
        List<LineSettingSeismicInfluenceflied> lineResultList = new ArrayList<>();
        //上传的文件id
        String fileIds = map.get("fileIds").toString();
        //烈度值字段
        String intensity = "";
        if(ObjectUtils.isNotEmpty(map.get("intensity"))){
            intensity = map.get("intensity").toString();
        }
        //地震事件id  1shp  2 gemjson
        String type = map.get("type").toString();
        //地震事件id
        String earthQuakeId = map.get("earthQuakeId").toString();
        //1--正式地震  2--测试地震  3--演练地震  4--自动地震, 默认是2 测试地震
        String flag = map.get("flag").toString();
        String code = request.getHeader("divisionCode");
        String divisionCode = code.split("_")[0];
        String userId = code.split("_")[1];
        log.error("地震id"+earthQuakeId+"-- 导入影响场"+"|| 开始。>> 参数:"+JSON.toJSONString(map));
        EarthQuake earthQuake = null;
        try{
            if("2".equals(flag) || "3".equals(flag)){
                //正式和自动的地震默认查询公共库，但是测试和演练的地震去各自专用库中查询地震信息
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            earthQuake = earthQuakeInfluenceService.getById(earthQuakeId);
            if("1".equals(flag) || "4".equals(flag)){
                //正式和自动的地震查询的是公共库，但是影响场信息保存在各自的专库中
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            if("1".equals(type)){
                ParsingResult shpData = this.getShpData(fileIds,intensity);
                if (!shpData.getMessage().equals("ok")) {
                    throw new RuntimeException(shpData.getMessage());
                }
                List<List<Object>> shpList = shpData.getShpList();
                if (ObjectUtils.isNotEmpty(shpList) && shpList.size()>0) {
                    for (List<Object> item : shpList) {
                        SettingSeismicInfluenceflied settingSeismicInfluenceflied = new SettingSeismicInfluenceflied();
                        settingSeismicInfluenceflied.setEarthQuakeId(earthQuakeId);
                        settingSeismicInfluenceflied.setVersion(DateUtil.date()+"");
                        settingSeismicInfluenceflied.setGeom(item.get(0).toString());
                        settingSeismicInfluenceflied.setDzIntensity(item.get(1).toString());
                        settingSeismicInfluenceflied.setIntensityShow(intensityMap().get(item.get(1).toString()));
                        settingSeismicInfluenceflied.setIntensityChinaShow(IntensityUtil.getUpperNum(item.get(1).toString()));
                        settingSeismicInfluenceflied.setTriggerType(earthQuake.getTrigMode());
                        settingSeismicInfluenceflied.setType(4);
                        settingSeismicInfluenceflied.setEarthquakeLevel(BigDecimal.valueOf(earthQuake.getEarthquakeMagnitude()));
                        settingSeismicInfluenceflied.setUuid(IdUtil.randomUUID().replace("-",""));
                        settingSeismicInfluenceflied.setDataSource(earthQuake.getEarthquakeType().toString());
                        settingSeismicInfluenceflied.setOperateUserId(userId);
                        settingSeismicInfluenceflied.setOperateTime(DateUtil.date());
                        //settingSeismicInfluenceflied.setOperateDeptId(dept.getId().toString());
                        settingSeismicInfluenceflied.setModelId("");
                        settingSeismicInfluenceflied.setCode("4490");
                        list.add(settingSeismicInfluenceflied);
                        String lineGeom = item.get(0).toString();
                        // 查询外壳与资源关联数量
                        String sql = "SELECT ST_ExteriorRing('"+lineGeom+"')";
                        lineGeom = jdbcTemplate.queryForObject(sql, String.class);
                        LineSettingSeismicInfluenceflied lineSettingSeismicInfluenceflied = new LineSettingSeismicInfluenceflied();
                        BeanUtils.copyProperties(settingSeismicInfluenceflied,lineSettingSeismicInfluenceflied);
                        lineSettingSeismicInfluenceflied.setGeom(lineGeom);
                        lineResultList.add(lineSettingSeismicInfluenceflied);
                    }
                }
            }else{
                String[] split = fileIds.split(",");
                String fileAbsPath = "";
                for (String id : split) {
                    //根据id和文件名获取真实的放在磁盘上的文件
                    AttachmentInfoEntity attachmentInfoEntity = attachmentService.getAttach(id);
                    String attachPath = attachmentInfoEntity.getAttachPath();
                    fileAbsPath = attachmentInfoEntity.getFileDirId() + File.separator + attachPath;
                }
                list = this.getJsonData(fileAbsPath,intensity,earthQuake,userId);
            }

            if (list.size()>0) {
                saveBatch(list);
                //计算影响场的机场、gdp、房屋面积
                String geomText = "POINT ("+earthQuake.getLongitude()+" "+earthQuake.getLatitude()+")";
                saveInfluenceOtherData(list,earthQuake,DynamicDataSourceContextHolder.peek(),geomText);
                log.error("地震id"+earthQuakeId+"-- 导入影响场"+"|| 成功。>> 参数:"+JSON.toJSONString(map));
            }
            if(lineResultList.size()>0){
                lineResultList.forEach(entity->{
                    lineInfluenceMapper.insert(entity);
                });
            }
        }catch (Exception ex){
            ex.printStackTrace();
            log.error("地震id"+earthQuakeId+"-- 导入影响场"+"|| 失败。>> 参数:"+JSON.toJSONString(map));
            throw new RuntimeException("保存影响场数据失败");
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
    }

    List<SettingSeismicInfluenceflied> getJsonData(String jsonPath, String intensityName, EarthQuake earthQuake,String userId){
        List<SettingSeismicInfluenceflied> list = new ArrayList<>();
        JSONParser parser = new JSONParser();
        try {
            Object obj = parser.parse(new FileReader(jsonPath));
            JSONObject jsonObject = (JSONObject) obj;
            JSONObject crsJson = (JSONObject) jsonObject.get("crs");
            JSONObject crsProperties = (JSONObject) crsJson.get("properties");
            String code = crsProperties.get("name").toString();
            //4490还是4326
            if(StringUtils.isBlank(code)){
                code = "4490";
            }else{
                code = code.split(":")[1];
            }
            String finalCode = code;
            JSONArray featuresArr = (JSONArray) jsonObject.get("features");
            featuresArr.forEach(js->{
                String geomText = "";
                JSONObject json = (JSONObject) js;
                JSONObject featureProperties = (JSONObject) json.get("properties");
                Long intensityVal = (Long) featureProperties.get(intensityName);
                if(ObjectUtils.isEmpty(intensityVal)){
                    intensityVal = (Long) featureProperties.get("intensity");
                }
                JSONObject geometry = (JSONObject) json.get("geometry");
                JSONArray coordinates = (JSONArray) geometry.get("coordinates");
                JSONArray coordinates1 = (JSONArray)  coordinates.get(0);
                JSONArray coordinates2 = (JSONArray)  coordinates1.get(0);
                StringBuilder sb = new StringBuilder("POLYGON((");
                coordinates2.forEach(coord->{
                    JSONArray cds = (JSONArray) coord;
                    String jwd = cds.toString();
                    jwd = jwd.replace("\"", "").replace("[","").replace("]","").replace(",", " ");
                    sb.append(jwd).append(",");
                });
                int index = sb.lastIndexOf(",");
                geomText = sb.substring(0, index);
                geomText+="))";
                SettingSeismicInfluenceflied settingSeismicInfluenceflied = new SettingSeismicInfluenceflied();
                settingSeismicInfluenceflied.setEarthQuakeId(earthQuake.getId()+"");
                settingSeismicInfluenceflied.setVersion(DateUtil.date()+"");
                settingSeismicInfluenceflied.setGeom(geomText);
                settingSeismicInfluenceflied.setDzIntensity(String.valueOf(intensityVal));
                settingSeismicInfluenceflied.setIntensityShow(intensityMap().get(String.valueOf(intensityVal)));
                settingSeismicInfluenceflied.setIntensityChinaShow(IntensityUtil.getUpperNum(String.valueOf(intensityVal)));
                settingSeismicInfluenceflied.setTriggerType(earthQuake.getTrigMode());
                settingSeismicInfluenceflied.setType(4);
                settingSeismicInfluenceflied.setEarthquakeLevel(BigDecimal.valueOf(earthQuake.getEarthquakeMagnitude()));
                settingSeismicInfluenceflied.setUuid(IdUtil.randomUUID().replace("-",""));
                settingSeismicInfluenceflied.setDataSource(earthQuake.getEarthquakeType().toString());
                settingSeismicInfluenceflied.setOperateUserId(userId);
                settingSeismicInfluenceflied.setOperateTime(DateUtil.date());
                //settingSeismicInfluenceflied.setOperateDeptId(dept.getId().toString());
                settingSeismicInfluenceflied.setModelId("");
                settingSeismicInfluenceflied.setCode(finalCode);
                list.add(settingSeismicInfluenceflied);
                String lineGeom = geomText;
                // 查询外壳与资源关联数量
                String sql = "SELECT ST_ExteriorRing('"+lineGeom+"')";
                lineGeom = jdbcTemplate.queryForObject(sql, String.class);
                LineSettingSeismicInfluenceflied lineSettingSeismicInfluenceflied = new LineSettingSeismicInfluenceflied();
                BeanUtils.copyProperties(settingSeismicInfluenceflied,lineSettingSeismicInfluenceflied);
                lineSettingSeismicInfluenceflied.setGeom(lineGeom);
                lineInfluenceMapper.insert(lineSettingSeismicInfluenceflied);
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
    public ParsingResult getShpData(String fileIds,String intensity) throws Exception {
        //.prj结尾用来校验是否为2000坐标系
        String prj = "";
        //.cpg文件用来获得编码格式,例如utf-8
        String cpg = "GBK";
        //.shp文件用来获得数据
        String shp = "";
        //根据id获取真实地址
        String[] split = fileIds.split(",");
        for (String id : split) {
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentService.getAttach(id);
            String attachPath = attachmentInfoEntity.getAttachPath();
            String substring = attachPath.substring(attachPath.length() - 4);
            if (substring.equals(".prj")) {
                prj = attachmentInfoEntity.getFileDirId() + attachPath;
            } else if (substring.equals(".shp")) {
                shp = attachmentInfoEntity.getFileDirId() + attachPath;
            } else if (substring.equals(".zip")) {
                String zipFilePath = attachmentInfoEntity.getFileDirId() +  attachPath;
                String root = StrUtil.removeSuffix(zipFilePath,".zip");
                ArrayList<MultipartFile> files = ZipUtils.decompress(zipFilePath);
                if(files.size()>0){
                    for (MultipartFile file : files) {
                        String originalFilename = file.getOriginalFilename();
                        if(originalFilename.contains("prj")){
                            prj = root + File.separator + originalFilename;
                        }
                        if(originalFilename.contains("shp") && !originalFilename.contains(".xml")){
                            shp = root + File.separator+ originalFilename;
                        }
                    }
                }
            }
        }
        return this.analytic(prj, cpg, shp,intensity);
    }
    public static ParsingResult analytic(String prj, String cpg, String shp,String intensity) {
        log.info("进行shp文件解析 >> {}", shp);
        //校验是否为2000或WGS_1984坐标系
        String code = ShpAnalyticUtil.checkCoordinateSystem(prj);
        if("".equals(code)){
            code = "4490";
        }else{
            if (!("4490".equals(code) || "4326".equals(code))) {
                log.info(new Date() + "-----------校验失败.请上传正确的坐标系数据及.prj文件.");
                return ParsingResult.shpData("请上传正确的坐标系数据及.prj文件", null);
            }
        }

        //读取cpg文件编码
        //String codeType = readCPG(cpg);
        String codeType = cpg;
        SimpleFeatureIterator iters = null;
        ArrayList<List<Object>> lists = new ArrayList<>();
        try {
            //获取shp数据
            SimpleFeatureCollection colls1 = ShpAnalyticUtil.readShp(shp, null, codeType);
            iters = colls1.features();
            while (iters.hasNext()) {
                SimpleFeature feature  = iters.next();
                Collection<Property> p = feature.getProperties();
                Iterator<Property> it = p.iterator();
                List<Object> rowList = new ArrayList<>();
                while (it.hasNext()){
                    Property pro = it.next();
                    String shpFieldName = String.valueOf(pro.getName());
                    String shpFieldVal = String.valueOf(pro.getValue());
                    if("the_geom".equals(shpFieldName)) {
                        if(pro.getValue() instanceof MultiPolygon) {
                            shpFieldVal = ((MultiPolygon)(pro.getValue())).getGeometryN(0).toString();
                            rowList.add(0,shpFieldVal);
                        }
                    }else if(intensity.equals(shpFieldName)){
                        rowList.add(1,shpFieldVal);
                    }
                }
                lists.add(rowList);
            }
            if (lists.size() == 0) {
                return ParsingResult.shpData("解析失败shp文件中没有数据", lists);
            }
        } finally {
            if (iters != null) {
                iters.close();
            }
        }
        log.info("shp文件解析成功 >> {}", shp);
        return ParsingResult.shpData("ok", lists);
    }

    private  List<SettingSeismicInfluenceflied> getInfluenceList(String influenceVersion, String earthQuakeId){
        //获取影响场数据
//        LambdaQueryWrapper<SettingSeismicInfluenceflied> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper.eq(SettingSeismicInfluenceflied::getVersion,influenceVersion).eq(SettingSeismicInfluenceflied::getEarthQuakeId,earthQuakeId);
        return settingInfluenceMapper.selectList1(influenceVersion,earthQuakeId);
    }
    /**
     * 快速评估--各烈度区面积、人口
     */
    @RabbitHandler
    @RabbitListener(queues = QueueConfig.QUEUE_INFLUENCE_TO_AREA_POP, ackMode = "MANUAL")
    public void createInfluenceAreaPop(Message message,Channel channel,Map<String,Object> toCreateAreaPop) throws IOException {
        CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String earthQuakeId = (String) toCreateAreaPop.get("earthQuakeId");
            Integer earthQuakeType = Integer.parseInt(toCreateAreaPop.get("earthQuakeType").toString());
            String  dataSourceKey = (String) toCreateAreaPop.get("dataSourceKey");
            String influenceVersion = (String) toCreateAreaPop.get("influenceVersion");
            try{
                if(StringUtils.isNotBlank(dataSourceKey)){
                    // 切换到省份数据源
                    DynamicDataSourceContextHolder.push("province_"+dataSourceKey);
                }
                List<SettingSeismicInfluenceflied> list = getInfluenceList(influenceVersion,earthQuakeId);
                if(ObjectUtils.isNotEmpty(list) && list.size()>0){
                    List<InfluenceAreaPersion> influenceAreaPersionList = new ArrayList<>();
                    for (SettingSeismicInfluenceflied influence : list) {
                        //面积
                        BigDecimal area = ObjectUtils.isNotEmpty(influence.getArea())?BigDecimal.valueOf(influence.getArea()).setScale(0,RoundingMode.HALF_UP):BigDecimal.ZERO;
                        //人口
                        //影响场和人口格网相交取值
//                        List<DataPop> dataPop = null;
//                        try{
//                            dataPop = popService.getBaseMapper().getByGeom(influence.getGeomText(), influence.getCode());
//                        }catch (UncategorizedSQLException e){
//                            if("4490".equals(influence.getCode())){
//                                influence.setCode("4326");
//                                dataPop = popService.getBaseMapper().getByGeom(influence.getGeomText(),influence.getCode());
//                            }else if("4326".equals(influence.getCode())){
//                                influence.setCode("4490");
//                                dataPop = popService.getBaseMapper().getByGeom(influence.getGeomText(), influence.getCode());
//                            }
//                        }
//                        //每个烈度圈的人口数
//                        if(dataPop==null){
//                            continue;
//                        }
                       // double population =  dataPop.stream().filter(ObjectUtils::isNotEmpty).mapToDouble(DataPop::getPopulation).sum();
                        double population = getPopNum(influence.getGeomText());
                        BigDecimal popNum = BigDecimal.valueOf(population).divide(BigDecimal.valueOf(10000),2,RoundingMode.HALF_DOWN);
                        //Double population = dataPop.get(0).getPopulation();
                        InfluenceAreaPersion influenceAreaPersion = new InfluenceAreaPersion();
                        influenceAreaPersion.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influence.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setArea(area.intValue()).setPopulation(popNum);
                        influenceAreaPersionList.add(influenceAreaPersion);
                    }
                    if(influenceAreaPersionList.size()>0){
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push("province_"+dataSourceKey);
                        LambdaQueryWrapper<InfluenceAreaPersion> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                        lambdaQueryWrapper.eq(InfluenceAreaPersion::getEarthquakeId,earthQuakeId);
                        influenceAreaPersionService.remove(lambdaQueryWrapper);
                        influenceAreaPersionService.saveBatch(influenceAreaPersionList);
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                String msgId = earthQuakeId;
                log.error("{},---快速评估--各烈度区面积、人口||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(toCreateAreaPop));
//                int retryCount = retryMap.getOrDefault(msgId, 0);
//                log.error("{},--快速评估--各烈度区面积、人口||失败,处理消息时发生错误:{},即将开始第{}次消息重试...",msgId,e.getMessage(),retryCount + 1, e);
//                if (retryCount >= failedRetry - 1) {
//                    log.error("{},---快速评估--各烈度区面积、人口||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(toCreateAreaPop));
//                    // 拒绝消息，并且不重新入队
//                    try {
//                        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.remove(msgId);
//                } else {
//                    // 重新发送消息到队列
//                    try {
//                        channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
//                                message.getMessageProperties().getReceivedRoutingKey(),
//                                MessageProperties.MINIMAL_PERSISTENT_BASIC,
//                                JSON.toJSONBytes(toCreateAreaPop));
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.put(msgId, retryCount + 1);
//                    log.error("{},--快速评估--各烈度区面积、人口||失败,消息重新入队,当前重试次数: {}", msgId,retryCount + 1);
//                }
            }finally {
                DynamicDataSourceContextHolder.clear();
            }
        },executor);


    }
    private double getPopNumBak(String geom){
        //影响场和省相交的那部分空间数据再和人口格网相交取值
        List<DataPop> dataPop  = popService.getBaseMapper().getByGeom(geom, "4490");
        if(ObjectUtils.isEmpty(dataPop) && !"province_root".equals(DynamicDataSourceContextHolder.peek())){
            //省级没查询到人口格网数据 就去查询国家专库的
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("province_root");
            dataPop = popService.getBaseMapper().getByGeom(geom, "4490");
        }
        //每个烈度圈的人口数  如果国家和省的人口数据都查询不到做0处理
        return ObjectUtils.isEmpty(dataPop)?0.0:dataPop.stream().mapToDouble(DataPop::getPopulation).sum();
    }
    private double getPopNum(String geom){
        //影响场和省相交的那部分空间数据再和人口格网相交取值
        DataPop dataPop  = popService.getBaseMapper().getByGeom1(geom, "4490");
        if(ObjectUtils.isEmpty(dataPop) && !"province_root".equals(DynamicDataSourceContextHolder.peek())){
            //省级没查询到人口格网数据 就去查询国家专库的
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("province_root");
            dataPop = popService.getBaseMapper().getByGeom1(geom, "4490");
        }
        //每个烈度圈的人口数  如果国家和省的人口数据都查询不到做0处理
        return ObjectUtils.isEmpty(dataPop)?0.0:dataPop.getPopulation();
//        return ObjectUtils.isEmpty(dataPop)?0.0:dataPop.stream().mapToDouble(DataPop::getPopulation).sum();
    }
    /**
     * 不同烈度下的医院学校水库统计
     */
    @RabbitHandler
    @RabbitListener(queues = QueueConfig.QUEUE_INFLUENCE_TO_STATICS, ackMode = "MANUAL")
    public void createInfluenceStatics(Message message,Channel channel,Map<String,Object> toCreateStatics) throws IOException {
        CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String earthQuakeId = (String) toCreateStatics.get("earthQuakeId");
            Integer earthQuakeType = Integer.parseInt(toCreateStatics.get("earthQuakeType").toString());
            String  dataSourceKey = (String) toCreateStatics.get("dataSourceKey");
            String influenceVersion = (String) toCreateStatics.get("influenceVersion");
            try{
                if(StringUtils.isNotBlank(dataSourceKey)){
                    // 切换到省份数据源
                    DynamicDataSourceContextHolder.push("province_"+dataSourceKey);
                }
                //获取影响场数据
                List<SettingSeismicInfluenceflied> list =  getInfluenceList(influenceVersion,earthQuakeId);
                if(ObjectUtils.isNotEmpty(list) && list.size()>0){
                    //水库标识
                    Map<String, Object> reservoirMap = getDataSourceKey("province_" + dataSourceKey, "data_reservoir");
                    int reservoirFlag = (int) reservoirMap.get("flag");
                    String reservoirDataSourceKey = (String) reservoirMap.get("dataSourceKey");
                    //综合医院标识
                    Map<String, Object> reDataSynthesizeMap = getDataSourceKey("province_" + dataSourceKey, "data_synthesize");
                    int reDataSynthesizeFlag = (int) reDataSynthesizeMap.get("flag");
                    String reDataSynthesizeDataSourceKey = (String) reDataSynthesizeMap.get("dataSourceKey");
                    //专科医院标识
                    Map<String, Object> reDataJuniorcollegeMap = getDataSourceKey("province_" + dataSourceKey, "data_juniorcollege");
                    int reDataJuniorcollegeFlag = (int) reDataJuniorcollegeMap.get("flag");
                    String reDataJuniorcollegeDataSourceKey = (String) reDataJuniorcollegeMap.get("dataSourceKey");
                    //幼儿园标识
                    Map<String, Object> reDataKindergartenMap = getDataSourceKey("province_" + dataSourceKey, "data_kindergarten");
                    int reDataKindergartenFlag = (int) reDataKindergartenMap.get("flag");
                    String reDataKindergartenDataSourceKey = (String) reDataKindergartenMap.get("dataSourceKey");
                    //小学标识
                    Map<String, Object> reDataPrimaryschoolMap = getDataSourceKey("province_" + dataSourceKey, "data_primaryschool");
                    int reDataPrimaryschoolFlag = (int) reDataPrimaryschoolMap.get("flag");
                    String reDataPrimaryschoolDataSourceKey = (String) reDataPrimaryschoolMap.get("dataSourceKey");
                    //中学标识
                    Map<String, Object> reDataMiddleschoolMap = getDataSourceKey("province_" + dataSourceKey, "data_middleschool");
                    int reDataMiddleschoolFlag = (int) reDataMiddleschoolMap.get("flag");
                    String reDataMiddleschoolDataSourceKey = (String) reDataMiddleschoolMap.get("dataSourceKey");
                    //高等标识
                    Map<String, Object> reDataHighacademyMap = getDataSourceKey("province_" + dataSourceKey, "data_highacademy");
                    int reDataHighacademyFlag = (int) reDataHighacademyMap.get("flag");
                    String reDataHighacademyDataSourceKey = (String) reDataHighacademyMap.get("dataSourceKey");

                    List<InfluencehospitalSchoolReservoir> schoolReservoirs = new ArrayList<>();
                    for (SettingSeismicInfluenceflied influenceflied : list) {
                        InfluencehospitalSchoolReservoir influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        //查询水库数量
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reservoirDataSourceKey);
                        List<Reservior> reserviors = reserviorMapper.selectCountByGeom(influenceflied.getGeomText());
                        int sknum = 0;
                        if(ObjectUtils.isNotEmpty(reserviors) || reserviors.size()>0){
                            sknum = reserviors.size();
                        }else{
                            swithDataSourceKey(reservoirFlag);
                            reserviors = reserviorMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reserviors) || reserviors.size()>0){
                                sknum = reserviors.size();
                            }
                        }
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("2").setDetailType("6")
                                .setNum(sknum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                        //综合医院
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reDataSynthesizeDataSourceKey);
                        List<ReDataSynthesize> reDataSynthesizes =  reDataSynthesizeMapper.selectCountByGeom(influenceflied.getGeomText());
                        int reDataSynthesizeNum = 0;
                        if(ObjectUtils.isNotEmpty(reDataSynthesizes) || reDataSynthesizes.size()>0){
                            reDataSynthesizeNum = reDataSynthesizes.size();
                        }else{
                            swithDataSourceKey(reDataSynthesizeFlag);
                            reDataSynthesizes = reDataSynthesizeMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reDataSynthesizes) || reDataSynthesizes.size()>0){
                                reDataSynthesizeNum = reDataSynthesizes.size();
                            }
                        }
                        influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("0").setDetailType("0")
                                .setNum(reDataSynthesizeNum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                        //专科医院
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reDataJuniorcollegeDataSourceKey);
                        List<ReDataJuniorcollege> reDataJuniorcolleges =  reDataJuniorcollegeMapper.selectCountByGeom(influenceflied.getGeomText());
                        int reDataJuniorcollegeNum = 0;
                        if(ObjectUtils.isNotEmpty(reDataJuniorcolleges) || reDataJuniorcolleges.size()>0){
                            reDataJuniorcollegeNum = reDataJuniorcolleges.size();
                        }else{
                            swithDataSourceKey(reDataJuniorcollegeFlag);
                            reDataJuniorcolleges = reDataJuniorcollegeMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reDataJuniorcolleges) || reDataJuniorcolleges.size()>0){
                                reDataJuniorcollegeNum = reDataJuniorcolleges.size();
                            }
                        }
                        influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("0").setDetailType("1")
                                .setNum(reDataJuniorcollegeNum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                        //幼儿园
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reDataKindergartenDataSourceKey);
                        List<ReDataKindergarten> reDataKindergartens =  reDataKindergartenMapper.selectCountByGeom(influenceflied.getGeomText());
                        int reDataKindergartenNum = 0;
                        if(ObjectUtils.isNotEmpty(reDataKindergartens) || reDataKindergartens.size()>0){
                            reDataKindergartenNum = reDataKindergartens.size();
                        }else{
                            swithDataSourceKey(reDataKindergartenFlag);
                            reDataKindergartens = reDataKindergartenMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reDataKindergartens) || reDataKindergartens.size()>0){
                                reDataKindergartenNum = reDataKindergartens.size();
                            }
                        }
                        influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("1").setDetailType("2")
                                .setNum(reDataKindergartenNum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                        //小学
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reDataPrimaryschoolDataSourceKey);
                        List<ReDataPrimaryschool> reDataPrimaryschools =  reDataPrimaryschoolMapper.selectCountByGeom(influenceflied.getGeomText());
                        int reDataPrimaryschoolNum = 0;
                        if(ObjectUtils.isNotEmpty(reDataPrimaryschools) || reDataPrimaryschools.size()>0){
                            reDataPrimaryschoolNum = reDataPrimaryschools.size();
                        }else{
                            swithDataSourceKey(reDataPrimaryschoolFlag);
                            reDataPrimaryschools = reDataPrimaryschoolMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reDataPrimaryschools) || reDataPrimaryschools.size()>0){
                                reDataPrimaryschoolNum = reDataPrimaryschools.size();
                            }
                        }
                        influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("1").setDetailType("3")
                                .setNum(reDataPrimaryschoolNum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                        //中学
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reDataMiddleschoolDataSourceKey);
                        List<ReDataMiddleschool> reDataMiddleschools =  reDataMiddleschoolMapper.selectCountByGeom(influenceflied.getGeomText());
                        int reDataMiddleschoolNum = 0;
                        if(ObjectUtils.isNotEmpty(reDataMiddleschools) || reDataMiddleschools.size()>0){
                            reDataMiddleschoolNum = reDataMiddleschools.size();
                        }else{
                            swithDataSourceKey(reDataMiddleschoolFlag);
                            reDataMiddleschools = reDataMiddleschoolMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reDataMiddleschools) || reDataMiddleschools.size()>0){
                                reDataMiddleschoolNum = reDataMiddleschools.size();
                            }
                        }
                        influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("1").setDetailType("4")
                                .setNum(reDataMiddleschoolNum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                        //高等院校
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(reDataHighacademyDataSourceKey);
                        List<ReDataHighacademy> reDataHighacademys =  reDataHighacademyMapper.selectCountByGeom(influenceflied.getGeomText());
                        int reDataHighacademyNum = 0;
                        if(ObjectUtils.isNotEmpty(reDataHighacademys) || reDataHighacademys.size()>0){
                            reDataHighacademyNum = reDataHighacademys.size();
                        }else{
                            swithDataSourceKey(reDataHighacademyFlag);
                            reDataHighacademys = reDataHighacademyMapper.selectCountByGeom(influenceflied.getGeomText());
                            if(ObjectUtils.isNotEmpty(reDataHighacademys) || reDataHighacademys.size()>0){
                                reDataHighacademyNum = reDataHighacademys.size();
                            }
                        }
                        influencehospitalSchoolReservoir = new InfluencehospitalSchoolReservoir();
                        influencehospitalSchoolReservoir.setId(cn.hutool.core.lang.UUID.randomUUID().toString().replace("-",""))
                                .setIntensity(influenceflied.getDzIntensity()).setEarthquakeId(earthQuakeId+"").setMainType("1").setDetailType("5")
                                .setNum(reDataHighacademyNum).setRemark("");
                        schoolReservoirs.add(influencehospitalSchoolReservoir);
                    }
                    if(schoolReservoirs.size()>0){
                        DynamicDataSourceContextHolder.clear();
                        //切换到专库
                        DynamicDataSourceContextHolder.push("province_"+dataSourceKey);
                        LambdaQueryWrapper<InfluencehospitalSchoolReservoir> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                        lambdaQueryWrapper.eq(InfluencehospitalSchoolReservoir::getEarthquakeId,earthQuakeId);
                        influencehospitalSchoolReservoirService.remove(lambdaQueryWrapper);
                        influencehospitalSchoolReservoirService.saveBatch(schoolReservoirs);
                    }
                }
            }catch (Exception e){
                e.printStackTrace();
                String msgId = earthQuakeId;
                log.error("{},---不同烈度下的医院学校水库统计||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(toCreateStatics));
//                int retryCount = retryMap.getOrDefault(msgId, 0);
//                log.error("{},--不同烈度下的医院学校水库统计||失败,处理消息时发生错误:{},即将开始第{}次消息重试...",msgId,e.getMessage(),retryCount + 1, e);
//                if (retryCount >= failedRetry - 1) {
//                    log.error("{},---不同烈度下的医院学校水库统计||失败,消息将被拒绝，>>参数:{}",msgId,JSON.toJSONString(toCreateStatics));
//                    // 拒绝消息，并且不重新入队
//                    try {
//                        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.remove(msgId);
//                } else {
//                    // 重新发送消息到队列
//                    try {
//                        channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
//                                message.getMessageProperties().getReceivedRoutingKey(),
//                                MessageProperties.MINIMAL_PERSISTENT_BASIC,
//                                JSON.toJSONBytes(toCreateStatics));
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.put(msgId, retryCount + 1);
//                    log.error("{},--不同烈度下的医院学校水库统计||失败,消息重新入队,当前重试次数: {}", msgId,retryCount + 1);
//                }
            }finally {
                DynamicDataSourceContextHolder.clear();
            }
        },executor);


    }

    private void swithDataSourceKey(int flag){
        if(1 == flag ){
            if(!"slave".equals(DynamicDataSourceContextHolder.peek())){
                //查询公库
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("slave");
            }
        }else{
            //查询国家专库
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("province_root");
        }
    }

    public List<InfluenceVO> correctDetail(String earthQuakeId, String influenceVersion,HttpServletRequest request) {
        String code = request.getHeader("divisionCode");
        String divisionCode = code.split("_")[0];
        List<InfluenceVO> voList = new ArrayList<>();
        //切换数据源
        try{
            DynamicDataSourceContextHolder.push("province_"+divisionCode);
            List<SettingSeismicInfluenceflied> list = settingInfluenceMapper.selectInfluence(earthQuakeId, influenceVersion);
            if(ObjectUtils.isNotEmpty(list) && list.size()>0){
                for (SettingSeismicInfluenceflied influenceflied : list) {
                    InfluenceVO vo = new InfluenceVO();
                    vo.setEarthQuakeId(earthQuakeId);
                    vo.setLongAxis(influenceflied.getLongX());
                    vo.setShortAxis(influenceflied.getShortY());
                    vo.setAngle(influenceflied.getAngle());
                    vo.setDzIntensity(influenceflied.getDzIntensity());
                    vo.setIntensityShow(influenceflied.getIntensityShow());
                    vo.setIntensityChinaShow(influenceflied.getIntensityChinaShow());
                    vo.setCategory(influenceflied.getCategory());
                    vo.setRuptureScale(influenceflied.getRuptureScale());
                    voList.add(vo);
                }

            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            DynamicDataSourceContextHolder.clear();
        }

        return voList;
    }
}
